From 5985cca2e60c2e053e50263c4d6e86c0adf1e4f3 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Mon, 16 Sep 2013 23:20:44 -0700 Subject: [PATCH 01/24] OpenGL2: Speed up fog shader slightly. --- code/renderergl2/glsl/fogpass_vp.glsl | 17 +++++++---------- code/renderergl2/glsl/generic_vp.glsl | 15 ++++++--------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/code/renderergl2/glsl/fogpass_vp.glsl b/code/renderergl2/glsl/fogpass_vp.glsl index f18bc707..40d14d9f 100644 --- a/code/renderergl2/glsl/fogpass_vp.glsl +++ b/code/renderergl2/glsl/fogpass_vp.glsl @@ -85,16 +85,13 @@ float CalcFog(vec4 position) float s = dot(position, u_FogDistance) * 8.0; float t = dot(position, u_FogDepth); - if (t < 1.0) - { - t = step(step(0.0, -u_FogEyeT), t); - } - else - { - t /= t - min(u_FogEyeT, 0.0); - } - - return s * t; + bool eyeOutside = u_FogEyeT < 0.0; + float t2 = float(t >= float(eyeOutside)); + + if (eyeOutside) + t2 *= t / (t - u_FogEyeT); + + return s * t2; } void main() diff --git a/code/renderergl2/glsl/generic_vp.glsl b/code/renderergl2/glsl/generic_vp.glsl index 67360b1b..9ad4489b 100644 --- a/code/renderergl2/glsl/generic_vp.glsl +++ b/code/renderergl2/glsl/generic_vp.glsl @@ -194,16 +194,13 @@ float CalcFog(vec4 position) float s = dot(position, u_FogDistance) * 8.0; float t = dot(position, u_FogDepth); - if (t < 1.0) - { - t = step(step(0.0, -u_FogEyeT), t); - } - else - { - t /= t - min(u_FogEyeT, 0.0); - } + bool eyeOutside = u_FogEyeT < 0.0; + float t2 = float(t >= float(eyeOutside)); - return s * t; + if (eyeOutside) + t2 *= t / (t - u_FogEyeT); + + return s * t2; } #endif From 42501db862a9c15577ca3b1d0b019ce994236db4 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Mon, 16 Sep 2013 23:41:04 -0700 Subject: [PATCH 02/24] OpenGL2: Some shader cleanup --- code/renderergl2/glsl/lightall_fp.glsl | 56 +++++++++++++++----------- code/renderergl2/glsl/lightall_vp.glsl | 42 ++++++++++--------- code/renderergl2/tr_shade.c | 2 +- 3 files changed, 57 insertions(+), 43 deletions(-) diff --git a/code/renderergl2/glsl/lightall_fp.glsl b/code/renderergl2/glsl/lightall_fp.glsl index 6aec2b4a..6dbfe963 100644 --- a/code/renderergl2/glsl/lightall_fp.glsl +++ b/code/renderergl2/glsl/lightall_fp.glsl @@ -261,6 +261,30 @@ vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float s return vec3(0.0); } + +float CalcLightAttenuation(vec3 dir, float sqrRadius) +{ + // point light at >0 radius, directional otherwise + float point = float(sqrRadius > 0.0); + + // inverse square light + float attenuation = sqrRadius / dot(dir, dir); + + // zero light at radius, approximating q3 style + // also don't attenuate directional light + attenuation = (0.5 * attenuation - 1.5) * point + 1.0; + + // clamp attenuation + #if defined(NO_LIGHT_CLAMP) + attenuation *= float(attenuation > 0.0); + #else + attenuation = clamp(attenuation, 0.0, 1.0); + #endif + + return attenuation; +} + + void main() { vec3 L, N, E, H; @@ -290,30 +314,12 @@ void main() #endif vec3 lightColor = lightSample.rgb; #elif defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT) - // inverse square light - float attenuation = u_LightRadius * u_LightRadius / dot(L, L); - - // zero light at radius, approximating q3 style - attenuation = 0.5 * attenuation - 0.5; - //attenuation = 0.0697168 * attenuation; - //attenuation *= step(0.294117, attenuation); - - // clamp attenuation - #if defined(NO_LIGHT_CLAMP) - attenuation *= step(0.0, attenuation); - #else - attenuation = clamp(attenuation, 0.0, 1.0); - #endif - - // don't attenuate directional light - attenuation = (attenuation - 1.0) * var_LightDir.w + 1.0; - - vec3 lightColor = u_DirectedLight * attenuation; + vec3 lightColor = u_DirectedLight * CalcLightAttenuation(L, u_LightRadius * u_LightRadius); vec3 ambientColor = u_AmbientLight; #elif defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT) vec3 lightColor = var_lightColor; #endif - + vec2 texCoords = var_DiffuseTex; #if defined(USE_PARALLAXMAP) @@ -360,9 +366,9 @@ void main() // surfaces not facing the light are always shadowed #if defined(USE_TANGENT_SPACE_LIGHT) - shadowValue *= step(0.0, var_PrimaryLightDir.z); + shadowValue *= float(var_PrimaryLightDir.z > 0.0); #else - shadowValue *= step(0.0, dot(var_Normal, var_PrimaryLightDir)); + shadowValue *= float(dot(var_Normal, var_PrimaryLightDir) > 0.0); #endif #if defined(SHADOWMAP_MODULATE) @@ -488,11 +494,13 @@ void main() reflectance = CalcDiffuse(diffuse.rgb, N, L, E, NE, NL, shininess); reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, shininess); + lightColor = u_PrimaryLightColor; // * CalcLightAttenuation(L, u_PrimaryLightRadius * u_PrimaryLightRadius); + #if defined(USE_SHADOWMAP) - reflectance *= shadowValue; + lightColor *= shadowValue; #endif - gl_FragColor.rgb += u_PrimaryLightColor * reflectance * NL; + gl_FragColor.rgb += lightColor * reflectance * NL; #endif #if defined(USE_LINEAR_LIGHT) diff --git a/code/renderergl2/glsl/lightall_vp.glsl b/code/renderergl2/glsl/lightall_vp.glsl index d2bfb395..3ea822a4 100644 --- a/code/renderergl2/glsl/lightall_vp.glsl +++ b/code/renderergl2/glsl/lightall_vp.glsl @@ -130,6 +130,29 @@ vec2 ModTexCoords(vec2 st, vec3 position, vec4 texMatrix, vec4 offTurb) #endif +float CalcLightAttenuation(vec3 dir, float sqrRadius) +{ + // point light at >0 radius, directional otherwise + float point = float(sqrRadius > 0.0); + + // inverse square light + float attenuation = sqrRadius / dot(dir, dir); + + // zero light at radius, approximating q3 style + // also don't attenuate directional light + attenuation = (0.5 * attenuation - 1.5) * point + 1.0; + + // clamp attenuation + #if defined(NO_LIGHT_CLAMP) + attenuation *= float(attenuation > 0.0); + #else + attenuation = clamp(attenuation, 0.0, 1.0); + #endif + + return attenuation; +} + + void main() { #if defined(USE_VERTEX_ANIMATION) @@ -187,24 +210,7 @@ void main() #endif #if defined(USE_LIGHT_VECTOR) && defined(USE_FAST_LIGHT) - // inverse square light - float attenuation = u_LightRadius * u_LightRadius / dot(L, L); - - // zero light at radius, approximating q3 style - attenuation = 0.5 * attenuation - 0.5; - //attenuation = 0.0697168 * attenuation; - //attenuation *= step(0.294117, attenuation); - - // clamp attenuation - #if defined(NO_LIGHT_CLAMP) - attenuation *= step(0.0, attenuation); - #else - attenuation = clamp(attenuation, 0.0, 1.0); - #endif - - // don't attenuate directional light - attenuation = (attenuation - 1.0) * u_LightOrigin.w + 1.0; - + float attenuation = CalcLightAttenuation(L, u_LightRadius * u_LightRadius); float NL = clamp(dot(normal, normalize(L)), 0.0, 1.0); var_Color.rgb *= u_DirectedLight * attenuation * NL + u_AmbientLight; diff --git a/code/renderergl2/tr_shade.c b/code/renderergl2/tr_shade.c index c704310b..4ee62984 100644 --- a/code/renderergl2/tr_shade.c +++ b/code/renderergl2/tr_shade.c @@ -1211,7 +1211,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) vec[3] = 0.0f; GLSL_SetUniformVec4(sp, UNIFORM_LIGHTORIGIN, vec); - GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, 999999.0f); + GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, 0.0f); } if (pStage->alphaGen == AGEN_PORTAL) From cbd05da5d12db002502090f3ba88afd915d6ae45 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Tue, 17 Sep 2013 15:33:46 -0700 Subject: [PATCH 03/24] OpenGL2: Fix for "unsupported framebuffer format" bug --- code/renderergl2/tr_image.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/renderergl2/tr_image.c b/code/renderergl2/tr_image.c index a80c975b..09031dc0 100644 --- a/code/renderergl2/tr_image.c +++ b/code/renderergl2/tr_image.c @@ -2303,6 +2303,9 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgT qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); + if (image->flags & IMGFLAG_MIPMAP) + qglGenerateMipmapEXT(GL_TEXTURE_CUBE_MAP); + image->uploadWidth = width; image->uploadHeight = height; } From 3ab895d1cdeef39bf8e1eda6ddd2feb18d296106 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Tue, 17 Sep 2013 23:52:40 -0700 Subject: [PATCH 04/24] OpenGL2: reduce varying usage in lightall shader. --- code/renderergl2/glsl/lightall_fp.glsl | 57 ++++++++++------------ code/renderergl2/glsl/lightall_vp.glsl | 67 +++++++++++++------------- 2 files changed, 60 insertions(+), 64 deletions(-) diff --git a/code/renderergl2/glsl/lightall_fp.glsl b/code/renderergl2/glsl/lightall_fp.glsl index 6dbfe963..5bc7b11a 100644 --- a/code/renderergl2/glsl/lightall_fp.glsl +++ b/code/renderergl2/glsl/lightall_fp.glsl @@ -24,45 +24,40 @@ uniform sampler2D u_ShadowMap; uniform samplerCube u_CubeMap; #endif -#if defined(USE_LIGHT_VECTOR) +#if defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT) uniform vec3 u_DirectedLight; uniform vec3 u_AmbientLight; -uniform float u_LightRadius; #endif #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) uniform vec3 u_PrimaryLightColor; uniform vec3 u_PrimaryLightAmbient; -uniform float u_PrimaryLightRadius; #endif -#if defined(USE_LIGHT) +#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT) uniform vec2 u_MaterialInfo; #endif -varying vec2 var_DiffuseTex; -#if defined(USE_LIGHTMAP) -varying vec2 var_LightTex; -#endif +varying vec4 var_TexCoords; + varying vec4 var_Color; #if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP) -varying vec3 var_ViewDir; -varying vec3 var_Normal; -varying vec3 var_Tangent; -varying vec3 var_Bitangent; +varying vec4 var_Normal; +varying vec4 var_Tangent; +varying vec4 var_Bitangent; #endif #if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT) -varying vec3 var_lightColor; +varying vec3 var_LightColor; #endif -#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) +#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT) varying vec4 var_LightDir; #endif #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) -varying vec3 var_PrimaryLightDir; +varying vec4 var_PrimaryLightDir; #endif @@ -276,7 +271,7 @@ float CalcLightAttenuation(vec3 dir, float sqrRadius) // clamp attenuation #if defined(NO_LIGHT_CLAMP) - attenuation *= float(attenuation > 0.0); + attenuation = max(attenuation, 0.0); #else attenuation = clamp(attenuation, 0.0, 1.0); #endif @@ -291,36 +286,36 @@ void main() float NL, NH, NE, EH; #if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP) - mat3 tangentToWorld = mat3(var_Tangent, var_Bitangent, var_Normal); + mat3 tangentToWorld = mat3(var_Tangent.xyz, var_Bitangent.xyz, var_Normal.xyz); #endif #if defined(USE_DELUXEMAP) - L = (2.0 * texture2D(u_DeluxeMap, var_LightTex).xyz - vec3(1.0)); + L = (2.0 * texture2D(u_DeluxeMap, var_TexCoords.zw).xyz - vec3(1.0)); #if defined(USE_TANGENT_SPACE_LIGHT) - L = L * tangentToWorld; + L = L * tangentToWorld; #endif #elif defined(USE_LIGHT) && !defined(USE_FAST_LIGHT) L = var_LightDir.xyz; #endif #if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP) - E = normalize(var_ViewDir); + E = normalize(vec3(var_Normal.w, var_Tangent.w, var_Bitangent.w)); #endif #if defined(USE_LIGHTMAP) - vec4 lightSample = texture2D(u_LightMap, var_LightTex).rgba; + vec4 lightSample = texture2D(u_LightMap, var_TexCoords.zw).rgba; #if defined(RGBM_LIGHTMAP) lightSample.rgb *= 32.0 * lightSample.a; #endif vec3 lightColor = lightSample.rgb; #elif defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT) - vec3 lightColor = u_DirectedLight * CalcLightAttenuation(L, u_LightRadius * u_LightRadius); + vec3 lightColor = u_DirectedLight * CalcLightAttenuation(L, var_LightDir.w); vec3 ambientColor = u_AmbientLight; #elif defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT) - vec3 lightColor = var_lightColor; + vec3 lightColor = var_LightColor; #endif - vec2 texCoords = var_DiffuseTex; + vec2 texCoords = var_TexCoords.xy; #if defined(USE_PARALLAXMAP) #if defined(USE_TANGENT_SPACE_LIGHT) @@ -355,7 +350,7 @@ void main() #elif defined(USE_TANGENT_SPACE_LIGHT) N = vec3(0.0, 0.0, 1.0); #else - N = normalize(var_Normal); + N = normalize(var_Normal.xyz); #endif L = normalize(L); @@ -368,7 +363,7 @@ void main() #if defined(USE_TANGENT_SPACE_LIGHT) shadowValue *= float(var_PrimaryLightDir.z > 0.0); #else - shadowValue *= float(dot(var_Normal, var_PrimaryLightDir) > 0.0); + shadowValue *= float(dot(var_Normal.xyz, var_PrimaryLightDir.xyz) > 0.0); #endif #if defined(SHADOWMAP_MODULATE) @@ -377,7 +372,7 @@ void main() #if 0 // Only shadow when the world light is parallel to the primary light - shadowValue = 1.0 + (shadowValue - 1.0) * clamp(dot(L, var_PrimaryLightDir), 0.0, 1.0); + shadowValue = 1.0 + (shadowValue - 1.0) * clamp(dot(L, var_PrimaryLightDir.xyz), 0.0, 1.0); #endif lightColor = mix(shadowColor, lightColor, shadowValue); #endif @@ -389,7 +384,7 @@ void main() #if defined(USE_TANGENT_SPACE_LIGHT) float surfNL = L.z; #else - float surfNL = clamp(dot(var_Normal, L), 0.0, 1.0); + float surfNL = clamp(dot(var_Normal.xyz, L), 0.0, 1.0); #endif // Scale the incoming light to compensate for the baked-in light angle @@ -474,7 +469,7 @@ void main() #if defined(USE_LIGHTMAP) cubeLightColor *= lightSample.rgb; #elif defined (USE_LIGHT_VERTEX) - cubeLightColor *= var_lightColor; + cubeLightColor *= var_LightColor; #else cubeLightColor *= lightColor * NL + ambientColor; #endif @@ -484,7 +479,7 @@ void main() #endif #if defined(USE_PRIMARY_LIGHT) - L = normalize(var_PrimaryLightDir); + L = normalize(var_PrimaryLightDir.xyz); NL = clamp(dot(N, L), 0.0, 1.0); H = normalize(L + E); @@ -494,7 +489,7 @@ void main() reflectance = CalcDiffuse(diffuse.rgb, N, L, E, NE, NL, shininess); reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, shininess); - lightColor = u_PrimaryLightColor; // * CalcLightAttenuation(L, u_PrimaryLightRadius * u_PrimaryLightRadius); + lightColor = u_PrimaryLightColor; // * CalcLightAttenuation(L, u_PrimaryLightDir.w); #if defined(USE_SHADOWMAP) lightColor *= shadowValue; diff --git a/code/renderergl2/glsl/lightall_vp.glsl b/code/renderergl2/glsl/lightall_vp.glsl index 3ea822a4..8230b9db 100644 --- a/code/renderergl2/glsl/lightall_vp.glsl +++ b/code/renderergl2/glsl/lightall_vp.glsl @@ -49,37 +49,30 @@ uniform float u_VertexLerp; #if defined(USE_LIGHT_VECTOR) uniform vec4 u_LightOrigin; - #if defined(USE_FAST_LIGHT) -uniform vec3 u_DirectedLight; -uniform vec3 u_AmbientLight; uniform float u_LightRadius; +uniform vec3 u_DirectedLight; + #if defined(USE_FAST_LIGHT) +uniform vec3 u_AmbientLight; #endif #endif #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) uniform vec4 u_PrimaryLightOrigin; +uniform float u_PrimaryLightRadius; #endif -varying vec2 var_DiffuseTex; - -#if defined(USE_LIGHTMAP) -varying vec2 var_LightTex; -#endif - -#if defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) -varying vec3 var_ViewDir; -#endif +varying vec4 var_TexCoords; varying vec4 var_Color; #if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP) -varying vec3 var_Normal; -varying vec3 var_Tangent; -varying vec3 var_Bitangent; +varying vec4 var_Normal; +varying vec4 var_Tangent; +varying vec4 var_Bitangent; #endif #if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT) -varying vec3 var_lightColor; +varying vec3 var_LightColor; #endif #if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT) @@ -87,7 +80,7 @@ varying vec4 var_LightDir; #endif #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) -varying vec3 var_PrimaryLightDir; +varying vec4 var_PrimaryLightDir; #endif #if defined(USE_TCGEN) @@ -144,7 +137,7 @@ float CalcLightAttenuation(vec3 dir, float sqrRadius) // clamp attenuation #if defined(NO_LIGHT_CLAMP) - attenuation *= float(attenuation > 0.0); + attenuation = max(attenuation, 0.0); #else attenuation = clamp(attenuation, 0.0, 1.0); #endif @@ -174,9 +167,9 @@ void main() #endif #if defined(USE_TCMOD) - var_DiffuseTex = ModTexCoords(texCoords, position, u_DiffuseTexMatrix, u_DiffuseTexOffTurb); + var_TexCoords.xy = ModTexCoords(texCoords, position, u_DiffuseTexMatrix, u_DiffuseTexOffTurb); #else - var_DiffuseTex = texCoords; + var_TexCoords.xy = texCoords; #endif gl_Position = u_ModelViewProjectionMatrix * vec4(position, 1.0); @@ -193,16 +186,16 @@ void main() #elif defined(USE_LIGHT) && !defined(USE_LIGHT_VECTOR) vec3 L = attr_LightDirection; #if defined(USE_MODELMATRIX) - L = (u_ModelMatrix * vec4(L, 0.0)).xyz; + L = (u_ModelMatrix * vec4(L, 0.0)).xyz; #endif #endif #if defined(USE_LIGHTMAP) - var_LightTex = attr_TexCoord1.st; + var_TexCoords.zw = attr_TexCoord1.st; #endif #if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT) - var_lightColor = u_VertColor.rgb * attr_Color.rgb; + var_LightColor = u_VertColor.rgb * attr_Color.rgb; var_Color.rgb = vec3(1.0); var_Color.a = u_VertColor.a * attr_Color.a + u_BaseColor.a; #else @@ -217,40 +210,48 @@ void main() #endif #if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP) - var_Normal = normal; - var_Tangent = tangent; - var_Bitangent = bitangent; + var_Normal.xyz = normal; + var_Tangent.xyz = tangent; + var_Bitangent.xyz = bitangent; #endif #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) - var_PrimaryLightDir = (u_PrimaryLightOrigin.xyz - (position * u_PrimaryLightOrigin.w)); + var_PrimaryLightDir.xyz = (u_PrimaryLightOrigin.xyz - (position * u_PrimaryLightOrigin.w)); + var_PrimaryLightDir.w = u_PrimaryLightRadius * u_PrimaryLightRadius; #endif #if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT) #if defined(USE_LIGHT_VECTOR) - var_LightDir = vec4(L, u_LightOrigin.w); + var_LightDir = vec4(L, u_LightRadius * u_LightRadius); #else var_LightDir = vec4(L, 0.0); #endif #endif -#if defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) - var_ViewDir = (u_ViewOrigin - position); +#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP) + vec3 viewDir = (u_ViewOrigin - position); #endif #if defined(USE_TANGENT_SPACE_LIGHT) mat3 tangentToWorld = mat3(tangent, bitangent, normal); #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) - var_PrimaryLightDir = var_PrimaryLightDir * tangentToWorld; + var_PrimaryLightDir.xyz = var_PrimaryLightDir.xyz * tangentToWorld; #endif #if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT) var_LightDir.xyz = var_LightDir.xyz * tangentToWorld; #endif - #if defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) - var_ViewDir = var_ViewDir * tangentToWorld; + #if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP) + viewDir = viewDir * tangentToWorld; #endif #endif + +#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP) + // store view direction in tangent space to save on varyings + var_Normal.w = viewDir.x; + var_Tangent.w = viewDir.y; + var_Bitangent.w = viewDir.z; +#endif } From fcaab903d12f46444873764c165bac70fbafc342 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Thu, 19 Sep 2013 21:41:27 -0500 Subject: [PATCH 05/24] Fix UI parse message for menu files Missing a space after colon. --- code/ui/ui_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ui/ui_main.c b/code/ui/ui_main.c index 21423cd2..6cdaa12c 100644 --- a/code/ui/ui_main.c +++ b/code/ui/ui_main.c @@ -849,7 +849,7 @@ void UI_ParseMenu(const char *menuFile) { int handle; pc_token_t token; - Com_Printf("Parsing menu file:%s\n", menuFile); + Com_Printf("Parsing menu file: %s\n", menuFile); handle = trap_PC_LoadSource(menuFile); if (!handle) { From 82be4e667fb950e0bb81c6f82a7f2a6216a33e25 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Fri, 20 Sep 2013 17:20:36 -0700 Subject: [PATCH 06/24] OpenGL2: Disable GL_ARB_seamless_cube_map by default, caused huge frame drops on some hardware --- code/renderergl2/tr_extensions.c | 6 ++++-- code/renderergl2/tr_init.c | 2 ++ code/renderergl2/tr_local.h | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/code/renderergl2/tr_extensions.c b/code/renderergl2/tr_extensions.c index 41cd9164..5cd5c2a5 100644 --- a/code/renderergl2/tr_extensions.c +++ b/code/renderergl2/tr_extensions.c @@ -701,8 +701,10 @@ void GLimp_InitExtraExtensions() glRefConfig.seamlessCubeMap = qfalse; if( GLimp_HaveExtension( extension ) ) { - glRefConfig.seamlessCubeMap = qtrue; - ri.Printf(PRINT_ALL, result[1], extension); + if (r_arb_seamless_cube_map->integer) + glRefConfig.seamlessCubeMap = qtrue; + + ri.Printf(PRINT_ALL, result[glRefConfig.seamlessCubeMap], extension); } else { diff --git a/code/renderergl2/tr_init.c b/code/renderergl2/tr_init.c index b9e5fb58..b9b90a47 100644 --- a/code/renderergl2/tr_init.c +++ b/code/renderergl2/tr_init.c @@ -100,6 +100,7 @@ cvar_t *r_ext_framebuffer_object; cvar_t *r_ext_texture_float; cvar_t *r_arb_half_float_pixel; cvar_t *r_ext_framebuffer_multisample; +cvar_t *r_arb_seamless_cube_map; cvar_t *r_mergeMultidraws; cvar_t *r_mergeLeafSurfaces; @@ -1133,6 +1134,7 @@ void R_Register( void ) r_ext_texture_float = ri.Cvar_Get( "r_ext_texture_float", "1", CVAR_ARCHIVE | CVAR_LATCH); r_arb_half_float_pixel = ri.Cvar_Get( "r_arb_half_float_pixel", "1", CVAR_ARCHIVE | CVAR_LATCH); r_ext_framebuffer_multisample = ri.Cvar_Get( "r_ext_framebuffer_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH); + r_arb_seamless_cube_map = ri.Cvar_Get( "r_arb_seamless_cube_map", "0", CVAR_ARCHIVE | CVAR_LATCH); r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic", "0", CVAR_ARCHIVE | CVAR_LATCH ); diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index 838845b4..74d216f2 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -1915,6 +1915,7 @@ extern cvar_t *r_ext_framebuffer_object; extern cvar_t *r_ext_texture_float; extern cvar_t *r_arb_half_float_pixel; extern cvar_t *r_ext_framebuffer_multisample; +extern cvar_t *r_arb_seamless_cube_map; extern cvar_t *r_nobind; // turns off binding to appropriate textures extern cvar_t *r_singleShader; // make most world faces use default shader From acbeca6042cb28b2fa3d38d4b44356f0a8604b53 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Tue, 24 Sep 2013 03:29:49 -0700 Subject: [PATCH 07/24] OpenGL2: Remove AGEN_FRESNEL(superceded by cubemap patch), and some small fixes and optimizations. --- code/renderergl2/glsl/fogpass_vp.glsl | 12 +- code/renderergl2/glsl/generic_vp.glsl | 33 +++--- code/renderergl2/glsl/lightall_fp.glsl | 92 +++++++-------- code/renderergl2/glsl/lightall_vp.glsl | 28 ++--- code/renderergl2/tr_glsl.c | 5 +- code/renderergl2/tr_local.h | 1 - code/renderergl2/tr_shade.c | 149 ++++++++++--------------- code/renderergl2/tr_shader.c | 50 +++------ 8 files changed, 157 insertions(+), 213 deletions(-) diff --git a/code/renderergl2/glsl/fogpass_vp.glsl b/code/renderergl2/glsl/fogpass_vp.glsl index 40d14d9f..ce0e015b 100644 --- a/code/renderergl2/glsl/fogpass_vp.glsl +++ b/code/renderergl2/glsl/fogpass_vp.glsl @@ -85,13 +85,13 @@ float CalcFog(vec4 position) float s = dot(position, u_FogDistance) * 8.0; float t = dot(position, u_FogDepth); - bool eyeOutside = u_FogEyeT < 0.0; - float t2 = float(t >= float(eyeOutside)); + float eyeOutside = step(0.0, -u_FogEyeT); + float fogged = step(eyeOutside, t); + + t = max(t, 1e-6); + t *= fogged / (t - u_FogEyeT * eyeOutside); - if (eyeOutside) - t2 *= t / (t - u_FogEyeT); - - return s * t2; + return s * t; } void main() diff --git a/code/renderergl2/glsl/generic_vp.glsl b/code/renderergl2/glsl/generic_vp.glsl index 9ad4489b..429d62f5 100644 --- a/code/renderergl2/glsl/generic_vp.glsl +++ b/code/renderergl2/glsl/generic_vp.glsl @@ -93,7 +93,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st) } else if (u_DeformGen == DGEN_WAVE_TRIANGLE) { - func = abs(fract(value + 0.75) - 0.5) * 4.0 - 1.0; + func = 1.0 - abs(4.0 * fract(value + 0.25) - 2.0); } else if (u_DeformGen == DGEN_WAVE_SAWTOOTH) { @@ -163,25 +163,20 @@ vec4 CalcColor(vec3 position, vec3 normal) color.rgb = clamp(u_DirectedLight * incoming + u_AmbientLight, 0.0, 1.0); } - vec3 toView = u_ViewOrigin - position; - vec3 viewer = normalize(u_ViewOrigin - position); + vec3 viewer = u_ViewOrigin - position; if (u_AlphaGen == AGEN_LIGHTING_SPECULAR) { - vec3 lightDir = normalize(vec3(-960.0, -1980.0, 96.0) - position.xyz); - vec3 halfangle = normalize(lightDir + viewer); + vec3 lightDir = normalize(vec3(-960.0, 1980.0, 96.0) - position.xyz); + vec3 reflected = -reflect(lightDir, normal); - color.a = pow(max(dot(normal, halfangle), 0.0), 8.0); + color.a = clamp(dot(reflected, normalize(viewer)), 0.0, 1.0); + color.a *= color.a; + color.a *= color.a; } else if (u_AlphaGen == AGEN_PORTAL) { - float alpha = length(toView) / u_PortalRange; - - color.a = clamp(alpha, 0.0, 1.0); - } - else if (u_AlphaGen == AGEN_FRESNEL) - { - color.a = 0.10 + 0.90 * pow(1.0 - dot(normal, viewer), 5); + color.a = clamp(length(viewer) / u_PortalRange, 0.0, 1.0); } return color; @@ -194,13 +189,13 @@ float CalcFog(vec4 position) float s = dot(position, u_FogDistance) * 8.0; float t = dot(position, u_FogDepth); - bool eyeOutside = u_FogEyeT < 0.0; - float t2 = float(t >= float(eyeOutside)); + float eyeOutside = step(0.0, -u_FogEyeT); + float fogged = step(eyeOutside, t); + + t = max(t, 1e-6); + t *= fogged / (t - u_FogEyeT * eyeOutside); - if (eyeOutside) - t2 *= t / (t - u_FogEyeT); - - return s * t2; + return s * t; } #endif diff --git a/code/renderergl2/glsl/lightall_fp.glsl b/code/renderergl2/glsl/lightall_fp.glsl index 5bc7b11a..f223bb0c 100644 --- a/code/renderergl2/glsl/lightall_fp.glsl +++ b/code/renderergl2/glsl/lightall_fp.glsl @@ -176,17 +176,21 @@ float CalcBlinn(float NH, float shininess) #endif } -float CalcGGX(float NH, float shininess) +float CalcGGX(float NH, float gloss) { - // from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes.pdf - float m_sq = 2.0 / shininess; - float d = ((NH * NH) * (m_sq - 1.0) + 1.0); - return m_sq / (d * d); + // from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf + float a_sq = exp2(gloss * -13.0 + 1.0); + float d = ((NH * NH) * (a_sq - 1.0) + 1.0); + return a_sq / (d * d); } float CalcFresnel(float EH) { #if 1 + // From http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf + // not accurate, but fast + return exp2(-10.0 * EH); +#elif 0 // From http://seblagarde.wordpress.com/2012/06/03/spherical-gaussien-approximation-for-blinn-phong-phong-and-fresnel/ return exp2((-5.55473 * EH - 6.98316) * EH); #elif 0 @@ -196,42 +200,48 @@ float CalcFresnel(float EH) return blend; #else - return pow(1.0 - NH, 5.0); + return pow(1.0 - EH, 5.0); #endif } -float CalcVisibility(float NH, float NL, float NE, float EH, float shininess) +float CalcVisibility(float NH, float NL, float NE, float EH, float gloss) { -#if 0 - float geo = 2.0 * NH * min(NE, NL); - geo /= max(EH, geo); - - return geo; -#else - // Modified from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes.pdf - // NL, NE in numerator factored out from cook-torrance +#if 1 + // From http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf + float k = min(1.0, gloss + 0.545); + return 1.0 / (k * EH * EH + (1.0 - k)); +#elif 0 + float roughness = exp2(gloss * -6.5); + #if defined(USE_GGX) - float roughness = sqrt(2.0 / (shininess + 2.0)); - float k = (roughness + 1.0); + // From http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf + float k = roughness + 1.0; k *= k * 0.125; #else - float k = 2.0 / sqrt(3.1415926535 * (shininess + 2.0)); + float k = roughness; #endif + // Modified from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf + // NL, NE in numerator factored out from cook-torrance float k2 = 1.0 - k; float invGeo1 = NL * k2 + k; float invGeo2 = NE * k2 + k; return 1.0 / (invGeo1 * invGeo2); - #endif +#else + float geo = 2.0 * NH * min(NE, NL); + geo /= max(EH, geo); + + return geo; +#endif } -vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float shininess) +vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float gloss, float shininess) { float blinn = CalcBlinn(NH, shininess); vec3 fSpecular = mix(specular, vec3(1.0), CalcFresnel(EH)); - float vis = CalcVisibility(NH, NL, NE, EH, shininess); + float vis = CalcVisibility(NH, NL, NE, EH, gloss); #if defined(USE_BLINN) // Normalized Blinn-Phong @@ -330,13 +340,12 @@ void main() #endif vec4 diffuse = texture2D(u_DiffuseMap, texCoords); +#if defined(USE_GAMMA2_TEXTURES) + diffuse.rgb *= diffuse.rgb; +#endif + #if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT) - - #if defined(USE_LINEAR_LIGHT) - diffuse.rgb *= diffuse.rgb; - #endif - #if defined(USE_NORMALMAP) #if defined(SWIZZLE_NORMALMAP) N.xy = 2.0 * texture2D(u_NormalMap, texCoords).ag - vec2(1.0); @@ -361,9 +370,9 @@ void main() // surfaces not facing the light are always shadowed #if defined(USE_TANGENT_SPACE_LIGHT) - shadowValue *= float(var_PrimaryLightDir.z > 0.0); + shadowValue *= step(0.0, var_PrimaryLightDir.z); #else - shadowValue *= float(dot(var_Normal.xyz, var_PrimaryLightDir.xyz) > 0.0); + shadowValue *= step(0.0, dot(var_Normal.xyz, var_PrimaryLightDir.xyz)); #endif #if defined(SHADOWMAP_MODULATE) @@ -403,9 +412,9 @@ void main() #if defined(USE_SPECULARMAP) vec4 specular = texture2D(u_SpecularMap, texCoords); - #if defined(USE_LINEAR_LIGHT) + #if defined(USE_GAMMA2_TEXTURES) specular.rgb *= specular.rgb; - #endif + #endif #else vec4 specular = vec4(1.0); #endif @@ -414,7 +423,6 @@ void main() float gloss = specular.a; float shininess = exp2(gloss * 13.0); - float localOcclusion = clamp((diffuse.r + diffuse.g + diffuse.b) * 16.0f, 0.0, 1.0); #if defined(SPECULAR_IS_METALLIC) // diffuse is actually base color, and red of specular is metallicness @@ -431,10 +439,12 @@ void main() reflectance = CalcDiffuse(diffuse.rgb, N, L, E, NE, NL, shininess); #if defined(r_deluxeSpecular) || defined(USE_LIGHT_VECTOR) + float adjGloss = gloss; float adjShininess = shininess; #if !defined(USE_LIGHT_VECTOR) - adjShininess = exp2(gloss * r_deluxeSpecular * 13.0); + adjGloss *= r_deluxeSpecular; + adjShininess = exp2(adjGloss * 13.0); #endif H = normalize(L + E); @@ -443,9 +453,9 @@ void main() NH = clamp(dot(N, H), 0.0, 1.0); #if !defined(USE_LIGHT_VECTOR) - reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjShininess) * r_deluxeSpecular * localOcclusion; + reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjGloss, adjShininess) * r_deluxeSpecular; #else - reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjShininess) * localOcclusion; + reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjGloss, adjShininess); #endif #endif @@ -462,10 +472,6 @@ void main() vec3 cubeLightColor = textureCubeLod(u_CubeMap, R, 7.0 - gloss * 7.0).rgb; - #if defined(USE_LINEAR_LIGHT) - cubeLightColor *= cubeLightColor; - #endif - #if defined(USE_LIGHTMAP) cubeLightColor *= lightSample.rgb; #elif defined (USE_LIGHT_VERTEX) @@ -475,11 +481,11 @@ void main() #endif //gl_FragColor.rgb += diffuse.rgb * textureCubeLod(u_CubeMap, N, 7.0).rgb; - gl_FragColor.rgb += cubeLightColor * reflectance * localOcclusion; + gl_FragColor.rgb += cubeLightColor * reflectance; #endif #if defined(USE_PRIMARY_LIGHT) - L = normalize(var_PrimaryLightDir.xyz); + L = var_PrimaryLightDir.xyz; //normalize(var_PrimaryLightDir.xyz); NL = clamp(dot(N, L), 0.0, 1.0); H = normalize(L + E); @@ -487,7 +493,7 @@ void main() NH = clamp(dot(N, H), 0.0, 1.0); reflectance = CalcDiffuse(diffuse.rgb, N, L, E, NE, NL, shininess); - reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, shininess); + reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, gloss, shininess); lightColor = u_PrimaryLightColor; // * CalcLightAttenuation(L, u_PrimaryLightDir.w); @@ -497,10 +503,6 @@ void main() gl_FragColor.rgb += lightColor * reflectance * NL; #endif - - #if defined(USE_LINEAR_LIGHT) - gl_FragColor.rgb = sqrt(gl_FragColor.rgb); - #endif gl_FragColor.a = diffuse.a; #else diff --git a/code/renderergl2/glsl/lightall_vp.glsl b/code/renderergl2/glsl/lightall_vp.glsl index 8230b9db..d9655ebe 100644 --- a/code/renderergl2/glsl/lightall_vp.glsl +++ b/code/renderergl2/glsl/lightall_vp.glsl @@ -113,7 +113,7 @@ vec2 ModTexCoords(vec2 st, vec3 position, vec4 texMatrix, vec4 offTurb) float phase = offTurb.w; vec2 st2 = vec2(dot(st, texMatrix.xz), dot(st, texMatrix.yw)) + offTurb.xy; - vec3 offsetPos = position * 0.0009765625; + vec3 offsetPos = position / 1024.0; offsetPos.x += offsetPos.z; vec2 texOffset = sin((offsetPos.xy + vec2(phase)) * 2.0 * M_PI); @@ -183,7 +183,7 @@ void main() #if defined(USE_LIGHT_VECTOR) vec3 L = u_LightOrigin.xyz - (position * u_LightOrigin.w); -#elif defined(USE_LIGHT) && !defined(USE_LIGHT_VECTOR) +#elif defined(USE_LIGHT) && !defined(USE_DELUXEMAP) vec3 L = attr_LightDirection; #if defined(USE_MODELMATRIX) L = (u_ModelMatrix * vec4(L, 0.0)).xyz; @@ -194,12 +194,10 @@ void main() var_TexCoords.zw = attr_TexCoord1.st; #endif -#if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT) - var_LightColor = u_VertColor.rgb * attr_Color.rgb; - var_Color.rgb = vec3(1.0); - var_Color.a = u_VertColor.a * attr_Color.a + u_BaseColor.a; -#else var_Color = u_VertColor * attr_Color + u_BaseColor; +#if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT) + var_LightColor = var_Color.rgb; + var_Color.rgb = vec3(1.0); #endif #if defined(USE_LIGHT_VECTOR) && defined(USE_FAST_LIGHT) @@ -209,14 +207,8 @@ void main() var_Color.rgb *= u_DirectedLight * attenuation * NL + u_AmbientLight; #endif -#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP) - var_Normal.xyz = normal; - var_Tangent.xyz = tangent; - var_Bitangent.xyz = bitangent; -#endif - #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) - var_PrimaryLightDir.xyz = (u_PrimaryLightOrigin.xyz - (position * u_PrimaryLightOrigin.w)); + var_PrimaryLightDir.xyz = u_PrimaryLightOrigin.xyz - (position * u_PrimaryLightOrigin.w); var_PrimaryLightDir.w = u_PrimaryLightRadius * u_PrimaryLightRadius; #endif @@ -229,7 +221,7 @@ void main() #endif #if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP) - vec3 viewDir = (u_ViewOrigin - position); + vec3 viewDir = u_ViewOrigin - position; #endif #if defined(USE_TANGENT_SPACE_LIGHT) @@ -250,8 +242,8 @@ void main() #if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP) // store view direction in tangent space to save on varyings - var_Normal.w = viewDir.x; - var_Tangent.w = viewDir.y; - var_Bitangent.w = viewDir.z; + var_Normal = vec4(normal, viewDir.x); + var_Tangent = vec4(tangent, viewDir.y); + var_Bitangent = vec4(bitangent, viewDir.z); #endif } diff --git a/code/renderergl2/tr_glsl.c b/code/renderergl2/tr_glsl.c index a2707cd0..93884b91 100644 --- a/code/renderergl2/tr_glsl.c +++ b/code/renderergl2/tr_glsl.c @@ -294,11 +294,9 @@ static void GLSL_GetShaderHeader( GLenum shaderType, const GLcharARB *extra, cha "#define alphaGen_t\n" "#define AGEN_LIGHTING_SPECULAR %i\n" "#define AGEN_PORTAL %i\n" - "#define AGEN_FRESNEL %i\n" "#endif\n", AGEN_LIGHTING_SPECULAR, - AGEN_PORTAL, - AGEN_FRESNEL)); + AGEN_PORTAL)); Q_strcat(dest, size, va("#ifndef texenv_t\n" @@ -1829,7 +1827,6 @@ shaderProgram_t *GLSL_GetGenericShaderProgram(int stage) { case AGEN_LIGHTING_SPECULAR: case AGEN_PORTAL: - case AGEN_FRESNEL: shaderAttribs |= GENERICDEF_USE_RGBAGEN; break; default: diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index 74d216f2..83b34d3a 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -241,7 +241,6 @@ typedef enum { AGEN_WAVEFORM, AGEN_PORTAL, AGEN_CONST, - AGEN_FRESNEL } alphaGen_t; typedef enum { diff --git a/code/renderergl2/tr_shade.c b/code/renderergl2/tr_shade.c index 4ee62984..a2b90c44 100644 --- a/code/renderergl2/tr_shade.c +++ b/code/renderergl2/tr_shade.c @@ -423,44 +423,27 @@ static void ProjectDlightTexture( void ) { static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t vertColor ) { + baseColor[0] = + baseColor[1] = + baseColor[2] = + baseColor[3] = 1.0f; + + vertColor[0] = + vertColor[1] = + vertColor[2] = + vertColor[3] = 0.0f; + // // rgbGen // switch ( pStage->rgbGen ) { - case CGEN_IDENTITY: - baseColor[0] = - baseColor[1] = - baseColor[2] = - baseColor[3] = 1.0f; - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; - break; case CGEN_IDENTITY_LIGHTING: baseColor[0] = baseColor[1] = baseColor[2] = tr.identityLight; - baseColor[3] = 1.0f; - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; break; case CGEN_EXACT_VERTEX: - baseColor[0] = - baseColor[1] = - baseColor[2] = - baseColor[3] = 0.0f; - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 1.0f; - break; case CGEN_EXACT_VERTEX_LIT: baseColor[0] = baseColor[1] = @@ -477,11 +460,6 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t baseColor[1] = pStage->constantColor[1] / 255.0f; baseColor[2] = pStage->constantColor[2] / 255.0f; baseColor[3] = pStage->constantColor[3] / 255.0f; - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; break; case CGEN_VERTEX: baseColor[0] = @@ -509,12 +487,10 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t baseColor[0] = baseColor[1] = baseColor[2] = tr.identityLight; - baseColor[3] = 1.0f; vertColor[0] = vertColor[1] = vertColor[2] = -tr.identityLight; - vertColor[3] = 0.0f; break; case CGEN_FOG: { @@ -527,22 +503,11 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t baseColor[2] = ((unsigned char *)(&fog->colorInt))[2] / 255.0f; baseColor[3] = ((unsigned char *)(&fog->colorInt))[3] / 255.0f; } - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; break; case CGEN_WAVEFORM: baseColor[0] = baseColor[1] = baseColor[2] = RB_CalcWaveColorSingle( &pStage->rgbWave ); - baseColor[3] = 1.0f; - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; break; case CGEN_ENTITY: if (backEnd.currentEntity) @@ -552,11 +517,6 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t baseColor[2] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f; baseColor[3] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; } - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; break; case CGEN_ONE_MINUS_ENTITY: if (backEnd.currentEntity) @@ -566,23 +526,10 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t baseColor[2] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f; baseColor[3] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; } - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; break; + case CGEN_IDENTITY: case CGEN_LIGHTING_DIFFUSE: case CGEN_BAD: - baseColor[0] = - baseColor[1] = - baseColor[2] = - baseColor[3] = 1.0f; - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; break; } @@ -593,10 +540,6 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t { case AGEN_SKIP: break; - case AGEN_IDENTITY: - baseColor[3] = 1.0f; - vertColor[3] = 0.0f; - break; case AGEN_CONST: baseColor[3] = pStage->constantColor[3] / 255.0f; vertColor[3] = 0.0f; @@ -627,9 +570,9 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t baseColor[3] = 1.0f; vertColor[3] = -1.0f; break; + case AGEN_IDENTITY: case AGEN_LIGHTING_SPECULAR: case AGEN_PORTAL: - case AGEN_FRESNEL: // Done entirely in vertex program baseColor[3] = 1.0f; vertColor[3] = 0.0f; @@ -1082,7 +1025,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) if (backEnd.depthFill) { - if (pStage->glslShaderGroup) + if (pStage->glslShaderGroup == tr.lightallShader) { int index = 0; @@ -1120,7 +1063,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) sp = &tr.genericShader[shaderAttribs]; } } - else if (pStage->glslShaderGroup) + else if (pStage->glslShaderGroup == tr.lightallShader) { int index = pStage->glslShaderIndex; @@ -1146,10 +1089,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) sp = &pStage->glslShaderGroup[index]; - if (pStage->glslShaderGroup == tr.lightallShader) - { - backEnd.pc.c_lightallDraws++; - } + backEnd.pc.c_lightallDraws++; } else { @@ -1269,7 +1209,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) else if ( pStage->bundle[TB_COLORMAP].image[0] != 0 ) R_BindAnimatedImageToTMU( &pStage->bundle[TB_COLORMAP], TB_COLORMAP ); } - else if ( pStage->glslShaderGroup ) + else if ( pStage->glslShaderGroup == tr.lightallShader ) { int i; @@ -1285,13 +1225,29 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) { - if (i == TB_LIGHTMAP) + image_t *img; + + if (pStage->bundle[i].image[0]) { - R_BindAnimatedImageToTMU( &pStage->bundle[i], i); - } - else if (pStage->bundle[i].image[0]) - { - GL_BindToTMU( tr.whiteImage, i); + switch(i) + { + case TB_LIGHTMAP: + R_BindAnimatedImageToTMU( &pStage->bundle[TB_LIGHTMAP], i); + break; + + case TB_DIFFUSEMAP: + case TB_SPECULARMAP: + case TB_SHADOWMAP: + case TB_CUBEMAP: + default: + GL_BindToTMU( tr.whiteImage, i); + break; + + case TB_NORMALMAP: + case TB_DELUXEMAP: + GL_BindToTMU( tr.greyImage, i); + break; + } } } } @@ -1299,15 +1255,32 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) { - if (i == TB_LIGHTMAP) + image_t *img; + + if (pStage->bundle[i].image[0]) { - R_BindAnimatedImageToTMU( &pStage->bundle[TB_DELUXEMAP], i); - } - else if (pStage->bundle[i].image[0]) - { - GL_BindToTMU( tr.whiteImage, i); + switch(i) + { + case TB_LIGHTMAP: + R_BindAnimatedImageToTMU( &pStage->bundle[TB_DELUXEMAP], i); + break; + + case TB_DIFFUSEMAP: + case TB_SPECULARMAP: + case TB_SHADOWMAP: + case TB_CUBEMAP: + default: + GL_BindToTMU( tr.whiteImage, i); + break; + + case TB_NORMALMAP: + case TB_DELUXEMAP: + GL_BindToTMU( tr.greyImage, i); + break; + } } } + } else { diff --git a/code/renderergl2/tr_shader.c b/code/renderergl2/tr_shader.c index c246127d..86186f05 100644 --- a/code/renderergl2/tr_shader.c +++ b/code/renderergl2/tr_shader.c @@ -1109,10 +1109,6 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) shader.portalRange = atof( token ); } } - else if ( !Q_stricmp( token, "fresnel" ) ) - { - stage->alphaGen = AGEN_FRESNEL; - } else { ri.Printf( PRINT_WARNING, "WARNING: unknown alphaGen parameter '%s' in shader '%s'\n", token, shader.name ); @@ -2011,7 +2007,6 @@ static void ComputeVertexAttribs(void) switch(pStage->alphaGen) { case AGEN_LIGHTING_SPECULAR: - case AGEN_FRESNEL: shader.vertexAttribs |= ATTR_NORMAL; break; @@ -2247,15 +2242,6 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse, defs |= LIGHTDEF_USE_PARALLAXMAP; } } - - if (!diffuse->bundle[TB_NORMALMAP].image[0]) - { - // use 0x80 image, shader will interpret as (0,0,1) - diffuse->bundle[TB_NORMALMAP] = diffuse->bundle[0]; - diffuse->bundle[TB_NORMALMAP].numImageAnimations = 0; - diffuse->bundle[TB_NORMALMAP].image[0] = tr.greyImage; - //ri.Printf(PRINT_ALL, ", normalmap %s", diffuse->bundle[TB_NORMALMAP].image[0]->imgName); - } } if (r_specularMapping->integer) @@ -2267,18 +2253,6 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse, diffuse->materialInfo[0] = specular->materialInfo[0]; diffuse->materialInfo[1] = specular->materialInfo[1]; } - else if (lightmap || useLightVector || useLightVertex) - { - // use a white image, materialinfo will do the rest - diffuse->bundle[TB_SPECULARMAP] = diffuse->bundle[0]; - diffuse->bundle[TB_SPECULARMAP].numImageAnimations = 0; - diffuse->bundle[TB_SPECULARMAP].image[0] = tr.whiteImage; - if (!diffuse->materialInfo[0]) - diffuse->materialInfo[0] = r_baseSpecular->value; - if (!diffuse->materialInfo[1]) - diffuse->materialInfo[1] = r_baseGloss->value; - //ri.Printf(PRINT_ALL, ", specularmap %s", diffuse->bundle[TB_SPECULARMAP].image[0]->imgName); - } } if (tcgen || diffuse->bundle[0].numTexMods) @@ -2372,7 +2346,6 @@ static qboolean CollapseStagesToGLSL(void) { case AGEN_LIGHTING_SPECULAR: case AGEN_PORTAL: - case AGEN_FRESNEL: skip = qtrue; break; default: @@ -2581,7 +2554,7 @@ static qboolean CollapseStagesToGLSL(void) } } - // convert any remaining lightingdiffuse stages to a lighting pass + // insert default normal and specular textures if necessary for (i = 0; i < MAX_SHADER_STAGES; i++) { shaderStage_t *pStage = &stages[i]; @@ -2589,14 +2562,27 @@ static qboolean CollapseStagesToGLSL(void) if (!pStage->active) continue; - if (pStage->rgbGen == CGEN_LIGHTING_DIFFUSE) + if (pStage->glslShaderGroup != tr.lightallShader) + continue; + + if ((pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) == 0) + continue; + + if (!pStage->bundle[TB_NORMALMAP].image[0] && r_normalMapping->integer) { - pStage->glslShaderGroup = tr.lightallShader; - pStage->glslShaderIndex = LIGHTDEF_USE_LIGHT_VECTOR; + pStage->bundle[TB_NORMALMAP].image[0] = tr.greyImage; + } + + if (!pStage->bundle[TB_SPECULARMAP].image[0] && r_specularMapping->integer) + { + pStage->bundle[TB_SPECULARMAP].image[0] = tr.whiteImage; + if (!pStage->materialInfo[0]) + pStage->materialInfo[0] = r_baseSpecular->value; + if (!pStage->materialInfo[1]) + pStage->materialInfo[1] = r_baseGloss->value; } } - return numStages; } From c6774cf113c15361156d6af7daca003c079d8649 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Mon, 7 Oct 2013 01:46:50 -0700 Subject: [PATCH 08/24] OpenGL2: default to RGBM lightmap, and add r_floatLightmap for old behaviour. --- code/renderergl2/tr_bsp.c | 4 ++-- code/renderergl2/tr_glsl.c | 4 ++-- code/renderergl2/tr_init.c | 2 ++ code/renderergl2/tr_local.h | 1 + 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/code/renderergl2/tr_bsp.c b/code/renderergl2/tr_bsp.c index 64d54805..3479be1a 100644 --- a/code/renderergl2/tr_bsp.c +++ b/code/renderergl2/tr_bsp.c @@ -271,7 +271,7 @@ static void R_LoadLightmaps( lump_t *l, lump_t *surfs ) { if (r_hdr->integer) { - if (glRefConfig.textureFloat && glRefConfig.halfFloatPixel) + if (glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer) textureInternalFormat = GL_RGBA16F_ARB; else textureInternalFormat = GL_RGBA8; @@ -410,7 +410,7 @@ static void R_LoadLightmaps( lump_t *l, lump_t *surfs ) { VectorScale(color, lightScale, color); - if (glRefConfig.textureFloat && glRefConfig.halfFloatPixel) + if (glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer) ColorToRGBA16F(color, (unsigned short *)(&image[j*8])); else ColorToRGBM(color, &image[j*4]); diff --git a/code/renderergl2/tr_glsl.c b/code/renderergl2/tr_glsl.c index 93884b91..54b05dc5 100644 --- a/code/renderergl2/tr_glsl.c +++ b/code/renderergl2/tr_glsl.c @@ -905,7 +905,7 @@ void GLSL_InitGPUShaders(void) if (i & GENERICDEF_USE_LIGHTMAP) Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n"); - if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel)) + if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer)) Q_strcat(extradefines, 1024, "#define RGBM_LIGHTMAP\n"); if (!GLSL_InitGPUShader(&tr.genericShader[i], "generic", attribs, qtrue, extradefines, qtrue, fallbackShader_generic_vp, fallbackShader_generic_fp)) @@ -1034,7 +1034,7 @@ void GLSL_InitGPUShaders(void) Q_strcat(extradefines, 1024, "#define SWIZZLE_NORMALMAP\n"); } - if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel)) + if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer)) Q_strcat(extradefines, 1024, "#define RGBM_LIGHTMAP\n"); if (i & LIGHTDEF_LIGHTTYPE_MASK) diff --git a/code/renderergl2/tr_init.c b/code/renderergl2/tr_init.c index b9b90a47..e17e1fd5 100644 --- a/code/renderergl2/tr_init.c +++ b/code/renderergl2/tr_init.c @@ -110,6 +110,7 @@ cvar_t *r_cameraExposure; cvar_t *r_softOverbright; cvar_t *r_hdr; +cvar_t *r_floatLightmap; cvar_t *r_postProcess; cvar_t *r_toneMap; @@ -1170,6 +1171,7 @@ void R_Register( void ) r_softOverbright = ri.Cvar_Get( "r_softOverbright", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_hdr = ri.Cvar_Get( "r_hdr", "1", CVAR_ARCHIVE | CVAR_LATCH ); + r_floatLightmap = ri.Cvar_Get( "r_floatLightmap", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_postProcess = ri.Cvar_Get( "r_postProcess", "1", CVAR_ARCHIVE ); r_toneMap = ri.Cvar_Get( "r_toneMap", "1", CVAR_ARCHIVE | CVAR_LATCH ); diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index 83b34d3a..5b864ce1 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -1958,6 +1958,7 @@ extern cvar_t *r_mergeLeafSurfaces; extern cvar_t *r_softOverbright; extern cvar_t *r_hdr; +extern cvar_t *r_floatLightmap; extern cvar_t *r_postProcess; extern cvar_t *r_toneMap; From e4227d1cd59f3a6877e1f18dc4c500fe499dc199 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Tue, 8 Oct 2013 08:01:00 -0500 Subject: [PATCH 09/24] Revert "5097 - Menu corrupted on start (on IRIX)" Calling glClear( any bits ) in GL_SetDefaultState makes connect screen black using the proprietary NVidia driver on Windows and GNU/Linux. This reverts commit 92573270de98a20cd78842bd2043cfe07bc5b2e1. --- code/renderergl1/tr_init.c | 10 ---------- code/renderergl2/tr_init.c | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/code/renderergl1/tr_init.c b/code/renderergl1/tr_init.c index 8ab50cd7..405c16d3 100644 --- a/code/renderergl1/tr_init.c +++ b/code/renderergl1/tr_init.c @@ -872,16 +872,6 @@ void GL_SetDefaultState( void ) qglEnable( GL_SCISSOR_TEST ); qglDisable( GL_CULL_FACE ); qglDisable( GL_BLEND ); - - qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); - qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); - qglClearDepth( 1.0 ); - - qglDrawBuffer( GL_FRONT ); - qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT ); - - qglDrawBuffer( GL_BACK ); - qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT ); } /* diff --git a/code/renderergl2/tr_init.c b/code/renderergl2/tr_init.c index e17e1fd5..c2ebf727 100644 --- a/code/renderergl2/tr_init.c +++ b/code/renderergl2/tr_init.c @@ -952,16 +952,6 @@ void GL_SetDefaultState( void ) qglDisable( GL_CULL_FACE ); qglDisable( GL_BLEND ); - qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); - qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); - qglClearDepth( 1.0 ); - - qglDrawBuffer( GL_FRONT ); - qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT ); - - qglDrawBuffer( GL_BACK ); - qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT ); - if (glRefConfig.seamlessCubeMap) qglEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); } From a836c2db891f7853602eab6bcd387518d638018a Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Wed, 9 Oct 2013 09:50:28 -0500 Subject: [PATCH 10/24] Drop sounds starting with * before allocating sfx slot Causes handle 0 to be returned by S_RegisterSound. --- code/client/snd_dma.c | 5 +++++ code/client/snd_mem.c | 5 ----- code/client/snd_openal.c | 9 +++++---- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/code/client/snd_dma.c b/code/client/snd_dma.c index d4ba8906..869c6197 100644 --- a/code/client/snd_dma.c +++ b/code/client/snd_dma.c @@ -271,6 +271,11 @@ static sfx_t *S_FindName( const char *name ) { return NULL; } + if (name[0] == '*') { + Com_Printf( S_COLOR_YELLOW "WARNING: Tried to load player sound directly: %s\n", name ); + return NULL; + } + hash = S_HashSFXName(name); sfx = sfxHash[hash]; diff --git a/code/client/snd_mem.c b/code/client/snd_mem.c index d42084b7..1031f34c 100644 --- a/code/client/snd_mem.c +++ b/code/client/snd_mem.c @@ -208,11 +208,6 @@ qboolean S_LoadSound( sfx_t *sfx ) snd_info_t info; // int size; - // player specific sounds are never directly loaded - if ( sfx->soundName[0] == '*') { - return qfalse; - } - // load it in data = S_CodecLoad(sfx->soundName, &info); if(!data) diff --git a/code/client/snd_openal.c b/code/client/snd_openal.c index 83eb541e..649c748e 100644 --- a/code/client/snd_openal.c +++ b/code/client/snd_openal.c @@ -208,6 +208,11 @@ static sfxHandle_t S_AL_BufferFind(const char *filename) return 0; } + if ( filename[0] == '*' ) { + Com_Printf( S_COLOR_YELLOW "WARNING: Tried to load player sound directly: %s\n", filename ); + return 0; + } + for(i = 0; i < numSfx; i++) { if(!Q_stricmp(knownSfx[i].filename, filename)) @@ -325,10 +330,6 @@ static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache) if(curSfx->filename[0] == '\0') return; - // Player SFX - if(curSfx->filename[0] == '*') - return; - // Already done? if((curSfx->inMemory) || (curSfx->isDefault) || (!cache && curSfx->isDefaultChecked)) return; From f8355ba2fba5a7d90ad24f33caeac19b910afb4b Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Thu, 10 Oct 2013 03:41:31 -0700 Subject: [PATCH 11/24] OpenGL2: Fix TCGEN_ENVIRONMENT stages not rendering correctly. --- code/renderergl2/glsl/generic_vp.glsl | 10 +++++----- code/renderergl2/glsl/lightall_vp.glsl | 3 ++- code/renderergl2/tr_glsl.c | 12 +++++++----- code/renderergl2/tr_light.c | 5 ++++- code/renderergl2/tr_local.h | 5 ++++- code/renderergl2/tr_shade.c | 3 +++ code/renderergl2/tr_shader.c | 15 +++++++++------ 7 files changed, 34 insertions(+), 19 deletions(-) diff --git a/code/renderergl2/glsl/generic_vp.glsl b/code/renderergl2/glsl/generic_vp.glsl index 429d62f5..94e3c83e 100644 --- a/code/renderergl2/glsl/generic_vp.glsl +++ b/code/renderergl2/glsl/generic_vp.glsl @@ -17,7 +17,7 @@ uniform vec4 u_DiffuseTexMatrix; uniform vec4 u_DiffuseTexOffTurb; #if defined(USE_TCGEN) || defined(USE_RGBAGEN) -uniform vec3 u_ViewOrigin; +uniform vec3 u_LocalViewOrigin; #endif #if defined(USE_TCGEN) @@ -48,7 +48,7 @@ uniform int u_ColorGen; uniform int u_AlphaGen; uniform vec3 u_AmbientLight; uniform vec3 u_DirectedLight; -uniform vec4 u_LightOrigin; +uniform vec3 u_ModelLightDir; uniform float u_PortalRange; #endif @@ -123,7 +123,7 @@ vec2 GenTexCoords(int TCGen, vec3 position, vec3 normal, vec3 TCGenVector0, vec3 } else if (TCGen == TCGEN_ENVIRONMENT_MAPPED) { - vec3 viewer = normalize(u_ViewOrigin - position); + vec3 viewer = normalize(u_LocalViewOrigin - position); tex = -reflect(viewer, normal).yz * vec2(0.5, -0.5) + 0.5; } else if (TCGen == TCGEN_VECTOR) @@ -158,12 +158,12 @@ vec4 CalcColor(vec3 position, vec3 normal) if (u_ColorGen == CGEN_LIGHTING_DIFFUSE) { - float incoming = clamp(dot(normal, u_LightOrigin.xyz), 0.0, 1.0); + float incoming = clamp(dot(normal, u_ModelLightDir), 0.0, 1.0); color.rgb = clamp(u_DirectedLight * incoming + u_AmbientLight, 0.0, 1.0); } - vec3 viewer = u_ViewOrigin - position; + vec3 viewer = u_LocalViewOrigin - position; if (u_AlphaGen == AGEN_LIGHTING_SPECULAR) { diff --git a/code/renderergl2/glsl/lightall_vp.glsl b/code/renderergl2/glsl/lightall_vp.glsl index d9655ebe..ce83d10a 100644 --- a/code/renderergl2/glsl/lightall_vp.glsl +++ b/code/renderergl2/glsl/lightall_vp.glsl @@ -22,6 +22,7 @@ attribute vec3 attr_LightDirection; #if defined(USE_TCGEN) || defined(USE_NORMALMAP) || defined(USE_LIGHT) && !defined(USE_FAST_LIGHT) uniform vec3 u_ViewOrigin; +uniform vec3 u_LocalViewOrigin; #endif #if defined(USE_TCGEN) @@ -94,7 +95,7 @@ vec2 GenTexCoords(int TCGen, vec3 position, vec3 normal, vec3 TCGenVector0, vec3 } else if (TCGen == TCGEN_ENVIRONMENT_MAPPED) { - vec3 viewer = normalize(u_ViewOrigin - position); + vec3 viewer = normalize(u_LocalViewOrigin - position); tex = -reflect(viewer, normal).yz * vec2(0.5, -0.5) + 0.5; } else if (TCGen == TCGEN_VECTOR) diff --git a/code/renderergl2/tr_glsl.c b/code/renderergl2/tr_glsl.c index 54b05dc5..dd6211be 100644 --- a/code/renderergl2/tr_glsl.c +++ b/code/renderergl2/tr_glsl.c @@ -106,6 +106,7 @@ static uniformInfo_t uniformsInfo[] = { "u_LightUp", GLSL_VEC3 }, { "u_LightRight", GLSL_VEC3 }, { "u_LightOrigin", GLSL_VEC4 }, + { "u_ModelLightDir", GLSL_VEC3 }, { "u_LightRadius", GLSL_FLOAT }, { "u_AmbientLight", GLSL_VEC3 }, { "u_DirectedLight", GLSL_VEC3 }, @@ -124,11 +125,12 @@ static uniformInfo_t uniformsInfo[] = { "u_VertexLerp" , GLSL_FLOAT }, { "u_MaterialInfo", GLSL_VEC2 }, - { "u_ViewInfo", GLSL_VEC4 }, - { "u_ViewOrigin", GLSL_VEC3 }, - { "u_ViewForward", GLSL_VEC3 }, - { "u_ViewLeft", GLSL_VEC3 }, - { "u_ViewUp", GLSL_VEC3 }, + { "u_ViewInfo", GLSL_VEC4 }, + { "u_ViewOrigin", GLSL_VEC3 }, + { "u_LocalViewOrigin", GLSL_VEC3 }, + { "u_ViewForward", GLSL_VEC3 }, + { "u_ViewLeft", GLSL_VEC3 }, + { "u_ViewUp", GLSL_VEC3 }, { "u_InvTexRes", GLSL_VEC2 }, { "u_AutoExposureMinMax", GLSL_VEC2 }, diff --git a/code/renderergl2/tr_light.c b/code/renderergl2/tr_light.c index ee7dad92..dc5a05d9 100644 --- a/code/renderergl2/tr_light.c +++ b/code/renderergl2/tr_light.c @@ -403,8 +403,11 @@ void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) { ((byte *)&ent->ambientLightInt)[3] = 0xff; // transform the direction to local space - // no need to do this if using lightentity glsl shader VectorNormalize( lightDir ); + ent->modelLightDir[0] = DotProduct( lightDir, ent->e.axis[0] ); + ent->modelLightDir[1] = DotProduct( lightDir, ent->e.axis[1] ); + ent->modelLightDir[2] = DotProduct( lightDir, ent->e.axis[2] ); + VectorCopy(lightDir, ent->lightDir); } diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index 5b864ce1..c19a1e1b 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -84,7 +84,8 @@ typedef struct { qboolean needDlights; // true for bmodels that touch a dlight qboolean lightingCalculated; qboolean mirrored; // mirrored matrix, needs reversed culling - vec3_t lightDir; // normalized direction towards light + vec3_t lightDir; // normalized direction towards light, in world space + vec3_t modelLightDir; // normalized direction towards light, in model space vec3_t ambientLight; // color normalized to 0-255 int ambientLightInt; // 32 bit rgba packed vec3_t directedLight; @@ -764,6 +765,7 @@ typedef enum UNIFORM_LIGHTUP, UNIFORM_LIGHTRIGHT, UNIFORM_LIGHTORIGIN, + UNIFORM_MODELLIGHTDIR, UNIFORM_LIGHTRADIUS, UNIFORM_AMBIENTLIGHT, UNIFORM_DIRECTEDLIGHT, @@ -784,6 +786,7 @@ typedef enum UNIFORM_VIEWINFO, // znear, zfar, width/2, height/2 UNIFORM_VIEWORIGIN, + UNIFORM_LOCALVIEWORIGIN, UNIFORM_VIEWFORWARD, UNIFORM_VIEWLEFT, UNIFORM_VIEWUP, diff --git a/code/renderergl2/tr_shade.c b/code/renderergl2/tr_shade.c index a2b90c44..c80f7679 100644 --- a/code/renderergl2/tr_shade.c +++ b/code/renderergl2/tr_shade.c @@ -719,6 +719,7 @@ static void ForwardDlight( void ) { GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); GLSL_SetUniformVec3(sp, UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin); + GLSL_SetUniformVec3(sp, UNIFORM_LOCALVIEWORIGIN, backEnd.or.viewOrigin); GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation); @@ -1102,6 +1103,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); GLSL_SetUniformVec3(sp, UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin); + GLSL_SetUniformVec3(sp, UNIFORM_LOCALVIEWORIGIN, backEnd.or.viewOrigin); GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation); @@ -1150,6 +1152,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) VectorCopy(backEnd.currentEntity->lightDir, vec); vec[3] = 0.0f; GLSL_SetUniformVec4(sp, UNIFORM_LIGHTORIGIN, vec); + GLSL_SetUniformVec3(sp, UNIFORM_MODELLIGHTDIR, backEnd.currentEntity->modelLightDir); GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, 0.0f); } diff --git a/code/renderergl2/tr_shader.c b/code/renderergl2/tr_shader.c index 86186f05..42f235cb 100644 --- a/code/renderergl2/tr_shader.c +++ b/code/renderergl2/tr_shader.c @@ -2282,7 +2282,7 @@ static qboolean CollapseStagesToGLSL(void) { // if 2+ stages and first stage is lightmap, switch them // this makes it easier for the later bits to process - if (stages[0].active && stages[0].bundle[0].isLightmap && stages[1].active) + if (stages[0].active && stages[0].bundle[0].tcGen == TCGEN_LIGHTMAP && stages[1].active) { int blendBits = stages[1].stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); @@ -2319,7 +2319,7 @@ static qboolean CollapseStagesToGLSL(void) break; } - if (pStage->bundle[0].isLightmap) + if (pStage->bundle[0].tcGen == TCGEN_LIGHTMAP) { int blendBits = pStage->stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); @@ -2370,7 +2370,7 @@ static qboolean CollapseStagesToGLSL(void) continue; // skip lightmaps - if (pStage->bundle[0].isLightmap) + if (pStage->bundle[0].tcGen == TCGEN_LIGHTMAP) continue; diffuse = pStage; @@ -2412,7 +2412,7 @@ static qboolean CollapseStagesToGLSL(void) break; case ST_COLORMAP: - if (pStage2->bundle[0].isLightmap) + if (pStage2->bundle[0].tcGen == TCGEN_LIGHTMAP) { lightmap = pStage2; } @@ -2454,7 +2454,7 @@ static qboolean CollapseStagesToGLSL(void) if (!pStage->active) continue; - if (pStage->bundle[0].isLightmap) + if (pStage->bundle[0].tcGen == TCGEN_LIGHTMAP) { pStage->active = qfalse; } @@ -2520,7 +2520,7 @@ static qboolean CollapseStagesToGLSL(void) if (pStage->adjustColorsForFog) continue; - if (pStage->bundle[TB_DIFFUSEMAP].isLightmap) + if (pStage->bundle[TB_DIFFUSEMAP].tcGen == TCGEN_LIGHTMAP) { pStage->glslShaderGroup = tr.lightallShader; pStage->glslShaderIndex = LIGHTDEF_USE_LIGHTMAP; @@ -2550,6 +2550,9 @@ static qboolean CollapseStagesToGLSL(void) { pStage->glslShaderGroup = tr.lightallShader; pStage->glslShaderIndex = LIGHTDEF_USE_LIGHT_VECTOR; + + if (pStage->bundle[0].tcGen != TCGEN_TEXTURE || pStage->bundle[0].numTexMods != 0) + pStage->glslShaderIndex |= LIGHTDEF_USE_TCGEN_AND_TCMOD; } } } From 08fcecc829b5820543d80dcde37ecb33f451b101 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Mon, 14 Oct 2013 01:55:54 -0700 Subject: [PATCH 12/24] OpenGL2: Clean up texmod calculations, and improve vertex animation handling. --- code/renderergl2/tr_glsl.c | 4 +- code/renderergl2/tr_local.h | 3 +- code/renderergl2/tr_shade.c | 107 +++--- code/renderergl2/tr_shade_calc.c | 570 ++----------------------------- code/renderergl2/tr_shader.c | 2 + code/renderergl2/tr_surface.c | 3 +- code/renderergl2/tr_vbo.c | 7 + 7 files changed, 92 insertions(+), 604 deletions(-) diff --git a/code/renderergl2/tr_glsl.c b/code/renderergl2/tr_glsl.c index dd6211be..8203e68b 100644 --- a/code/renderergl2/tr_glsl.c +++ b/code/renderergl2/tr_glsl.c @@ -1696,7 +1696,7 @@ void GLSL_VertexAttribPointers(uint32_t attribBits) // position/normal/tangent/bitangent are always set in case of animation oldFrame = glState.vertexAttribsOldFrame; newFrame = glState.vertexAttribsNewFrame; - animated = (oldFrame != newFrame) && (glState.vertexAttribsInterpolation > 0.0f); + animated = glState.vertexAnimation; if((attribBits & ATTR_POSITION) && (!(glState.vertexAttribPointersSet & ATTR_POSITION) || animated)) { @@ -1845,7 +1845,7 @@ shaderProgram_t *GLSL_GetGenericShaderProgram(int stage) shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES; } - if (glState.vertexAttribsInterpolation > 0.0f && backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) + if (glState.vertexAnimation) { shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION; } diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index c19a1e1b..82fbb004 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -1566,6 +1566,7 @@ typedef struct { uint32_t vertexAttribsNewFrame; uint32_t vertexAttribsOldFrame; float vertexAttribsInterpolation; + qboolean vertexAnimation; shaderProgram_t *currentProgram; FBO_t *currentFBO; VBO_t *currentVBO; @@ -2514,7 +2515,7 @@ void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *dstTexCoords ); void RB_CalcScaleTexMatrix( const float scale[2], float *matrix ); void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix ); void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix ); -void RB_CalcTurbulentTexMatrix( const waveForm_t *wf, matrix_t matrix ); +void RB_CalcTurbulentFactors( const waveForm_t *wf, float *amplitude, float *now ); void RB_CalcTransformTexMatrix( const texModInfo_t *tmi, float *matrix ); void RB_CalcStretchTexMatrix( const waveForm_t *wf, float *matrix ); diff --git a/code/renderergl2/tr_shade.c b/code/renderergl2/tr_shade.c index c80f7679..6ccbacf1 100644 --- a/code/renderergl2/tr_shade.c +++ b/code/renderergl2/tr_shade.c @@ -221,14 +221,22 @@ extern float EvalWaveForm( const waveForm_t *wf ); extern float EvalWaveFormClamped( const waveForm_t *wf ); -static void ComputeTexMatrix( shaderStage_t *pStage, int bundleNum, float *outmatrix) +static void ComputeTexMods( shaderStage_t *pStage, int bundleNum, float *outMatrix, float *outOffTurb) { int tm; - float matrix[16], currentmatrix[16]; + float matrix[6], currentmatrix[6]; textureBundle_t *bundle = &pStage->bundle[bundleNum]; - Matrix16Identity(outmatrix); - Matrix16Identity(currentmatrix); + matrix[0] = 1.0f; matrix[2] = 0.0f; matrix[4] = 0.0f; + matrix[1] = 0.0f; matrix[3] = 1.0f; matrix[5] = 0.0f; + + currentmatrix[0] = 1.0f; currentmatrix[2] = 0.0f; currentmatrix[4] = 0.0f; + currentmatrix[1] = 0.0f; currentmatrix[3] = 1.0f; currentmatrix[5] = 0.0f; + + outMatrix[0] = 1.0f; outMatrix[2] = 0.0f; + outMatrix[1] = 0.0f; outMatrix[3] = 1.0f; + + outOffTurb[0] = 0.0f; outOffTurb[1] = 0.0f; outOffTurb[2] = 0.0f; outOffTurb[3] = 0.0f; for ( tm = 0; tm < bundle->numTexMods ; tm++ ) { switch ( bundle->texMods[tm].type ) @@ -239,59 +247,73 @@ static void ComputeTexMatrix( shaderStage_t *pStage, int bundleNum, float *outma break; case TMOD_TURBULENT: - RB_CalcTurbulentTexMatrix( &bundle->texMods[tm].wave, - matrix ); - outmatrix[12] = matrix[12]; - outmatrix[13] = matrix[13]; - Matrix16Copy(outmatrix, currentmatrix); + RB_CalcTurbulentFactors(&bundle->texMods[tm].wave, &outOffTurb[2], &outOffTurb[3]); break; case TMOD_ENTITY_TRANSLATE: - RB_CalcScrollTexMatrix( backEnd.currentEntity->e.shaderTexCoord, - matrix ); - Matrix16Multiply(matrix, currentmatrix, outmatrix); - Matrix16Copy(outmatrix, currentmatrix); + RB_CalcScrollTexMatrix( backEnd.currentEntity->e.shaderTexCoord, matrix ); break; case TMOD_SCROLL: RB_CalcScrollTexMatrix( bundle->texMods[tm].scroll, matrix ); - Matrix16Multiply(matrix, currentmatrix, outmatrix); - Matrix16Copy(outmatrix, currentmatrix); break; case TMOD_SCALE: RB_CalcScaleTexMatrix( bundle->texMods[tm].scale, matrix ); - Matrix16Multiply(matrix, currentmatrix, outmatrix); - Matrix16Copy(outmatrix, currentmatrix); break; case TMOD_STRETCH: RB_CalcStretchTexMatrix( &bundle->texMods[tm].wave, matrix ); - Matrix16Multiply(matrix, currentmatrix, outmatrix); - Matrix16Copy(outmatrix, currentmatrix); break; case TMOD_TRANSFORM: RB_CalcTransformTexMatrix( &bundle->texMods[tm], matrix ); - Matrix16Multiply(matrix, currentmatrix, outmatrix); - Matrix16Copy(outmatrix, currentmatrix); break; case TMOD_ROTATE: RB_CalcRotateTexMatrix( bundle->texMods[tm].rotateSpeed, matrix ); - Matrix16Multiply(matrix, currentmatrix, outmatrix); - Matrix16Copy(outmatrix, currentmatrix); break; default: ri.Error( ERR_DROP, "ERROR: unknown texmod '%d' in shader '%s'", bundle->texMods[tm].type, tess.shader->name ); break; } + + switch ( bundle->texMods[tm].type ) + { + case TMOD_NONE: + case TMOD_TURBULENT: + default: + break; + + case TMOD_ENTITY_TRANSLATE: + case TMOD_SCROLL: + case TMOD_SCALE: + case TMOD_STRETCH: + case TMOD_TRANSFORM: + case TMOD_ROTATE: + outMatrix[0] = matrix[0] * currentmatrix[0] + matrix[2] * currentmatrix[1]; + outMatrix[1] = matrix[1] * currentmatrix[0] + matrix[3] * currentmatrix[1]; + + outMatrix[2] = matrix[0] * currentmatrix[2] + matrix[2] * currentmatrix[3]; + outMatrix[3] = matrix[1] * currentmatrix[2] + matrix[3] * currentmatrix[3]; + + outOffTurb[0] = matrix[0] * currentmatrix[4] + matrix[2] * currentmatrix[5] + matrix[4]; + outOffTurb[1] = matrix[1] * currentmatrix[4] + matrix[3] * currentmatrix[5] + matrix[5]; + + currentmatrix[0] = outMatrix[0]; + currentmatrix[1] = outMatrix[1]; + currentmatrix[2] = outMatrix[2]; + currentmatrix[3] = outMatrix[3]; + currentmatrix[4] = outOffTurb[0]; + currentmatrix[5] = outOffTurb[1]; + break; + } } } @@ -692,7 +714,8 @@ static void ForwardDlight( void ) { dlight_t *dl; shaderProgram_t *sp; vec4_t vector; - matrix_t matrix; + vec4_t texMatrix; + vec4_t texOffTurb; if ( !( tess.dlightBits & ( 1 << l ) ) ) { continue; // this surface definately doesn't have any of this light @@ -795,13 +818,9 @@ static void ForwardDlight( void ) { GL_SelectTexture(0); } - ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix ); - - VectorSet4(vector, matrix[0], matrix[1], matrix[4], matrix[5]); - GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, vector); - - VectorSet4(vector, matrix[8], matrix[9], matrix[12], matrix[13]); - GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector); + ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb ); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, texOffTurb); GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen); @@ -926,7 +945,7 @@ static void RB_FogPass( void ) { if (deformGen != DGEN_NONE) index |= FOGDEF_USE_DEFORM_VERTEXES; - if (glState.vertexAttribsInterpolation) + if (glState.vertexAnimation) index |= FOGDEF_USE_VERTEX_ANIMATION; sp = &tr.fogShader[index]; @@ -983,7 +1002,7 @@ static unsigned int RB_CalcShaderVertexAttribs( shaderCommands_t *input ) { unsigned int vertexAttribs = input->shader->vertexAttribs; - if(glState.vertexAttribsInterpolation > 0.0f) + if(glState.vertexAnimation) { vertexAttribs |= ATTR_POSITION2; if (vertexAttribs & ATTR_NORMAL) @@ -1002,7 +1021,6 @@ static unsigned int RB_CalcShaderVertexAttribs( shaderCommands_t *input ) static void RB_IterateStagesGeneric( shaderCommands_t *input ) { int stage; - matrix_t matrix; vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0}; float eyeT = 0; @@ -1018,6 +1036,8 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { shaderStage_t *pStage = input->xstages[stage]; shaderProgram_t *sp; + vec4_t texMatrix; + vec4_t texOffTurb; if ( !pStage ) { @@ -1051,7 +1071,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES; } - if (glState.vertexAttribsInterpolation > 0.0f && backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) + if (glState.vertexAnimation) { shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION; } @@ -1174,16 +1194,9 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) GLSL_SetUniformVec4(sp, UNIFORM_FOGCOLORMASK, fogColorMask); } - ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix ); - - { - vec4_t vector; - VectorSet4(vector, matrix[0], matrix[1], matrix[4], matrix[5]); - GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, vector); - - VectorSet4(vector, matrix[8], matrix[9], matrix[12], matrix[13]); - GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector); - } + ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb ); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, texOffTurb); GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen); if (pStage->bundle[0].tcGen == TCGEN_VECTOR) @@ -1228,8 +1241,6 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) { - image_t *img; - if (pStage->bundle[i].image[0]) { switch(i) @@ -1258,8 +1269,6 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) { - image_t *img; - if (pStage->bundle[i].image[0]) { switch(i) diff --git a/code/renderergl2/tr_shade_calc.c b/code/renderergl2/tr_shade_calc.c index a5c4e9ab..faab03e5 100644 --- a/code/renderergl2/tr_shade_calc.c +++ b/code/renderergl2/tr_shade_calc.c @@ -84,42 +84,16 @@ static float EvalWaveFormClamped( const waveForm_t *wf ) } /* -** RB_CalcStretchTexCoords +** RB_CalcStretchTexMatrix */ -void RB_CalcStretchTexCoords( const waveForm_t *wf, float *st ) -{ - float p; - texModInfo_t tmi; - - p = 1.0f / EvalWaveForm( wf ); - - tmi.matrix[0][0] = p; - tmi.matrix[1][0] = 0; - tmi.translate[0] = 0.5f - 0.5f * p; - - tmi.matrix[0][1] = 0; - tmi.matrix[1][1] = p; - tmi.translate[1] = 0.5f - 0.5f * p; - - RB_CalcTransformTexCoords( &tmi, st ); -} - void RB_CalcStretchTexMatrix( const waveForm_t *wf, float *matrix ) { float p; - texModInfo_t tmi; p = 1.0f / EvalWaveForm( wf ); - tmi.matrix[0][0] = p; - tmi.matrix[1][0] = 0; - tmi.translate[0] = 0.5f - 0.5f * p; - - tmi.matrix[0][1] = 0; - tmi.matrix[1][1] = p; - tmi.translate[1] = 0.5f - 0.5f * p; - - RB_CalcTransformTexMatrix( &tmi, matrix ); + matrix[0] = p; matrix[2] = 0; matrix[4] = 0.5f - 0.5f * p; + matrix[1] = 0; matrix[3] = p; matrix[5] = 0.5f - 0.5f * p; } /* @@ -618,88 +592,6 @@ COLORS */ -/* -** RB_CalcColorFromEntity -*/ -void RB_CalcColorFromEntity( unsigned char *dstColors ) -{ - int i; - int *pColors = ( int * ) dstColors; - int c; - - if ( !backEnd.currentEntity ) - return; - - c = * ( int * ) backEnd.currentEntity->e.shaderRGBA; - - for ( i = 0; i < tess.numVertexes; i++, pColors++ ) - { - *pColors = c; - } -} - -/* -** RB_CalcColorFromOneMinusEntity -*/ -void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors ) -{ - int i; - int *pColors = ( int * ) dstColors; - unsigned char invModulate[4]; - int c; - - if ( !backEnd.currentEntity ) - return; - - invModulate[0] = 255 - backEnd.currentEntity->e.shaderRGBA[0]; - invModulate[1] = 255 - backEnd.currentEntity->e.shaderRGBA[1]; - invModulate[2] = 255 - backEnd.currentEntity->e.shaderRGBA[2]; - invModulate[3] = 255 - backEnd.currentEntity->e.shaderRGBA[3]; // this trashes alpha, but the AGEN block fixes it - - c = * ( int * ) invModulate; - - for ( i = 0; i < tess.numVertexes; i++, pColors++ ) - { - *pColors = c; - } -} - -/* -** RB_CalcAlphaFromEntity -*/ -void RB_CalcAlphaFromEntity( unsigned char *dstColors ) -{ - int i; - - if ( !backEnd.currentEntity ) - return; - - dstColors += 3; - - for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 ) - { - *dstColors = backEnd.currentEntity->e.shaderRGBA[3]; - } -} - -/* -** RB_CalcAlphaFromOneMinusEntity -*/ -void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors ) -{ - int i; - - if ( !backEnd.currentEntity ) - return; - - dstColors += 3; - - for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 ) - { - *dstColors = 0xff - backEnd.currentEntity->e.shaderRGBA[3]; - } -} - /* ** RB_CalcWaveColorSingle */ @@ -723,29 +615,6 @@ float RB_CalcWaveColorSingle( const waveForm_t *wf ) return glow; } -/* -** RB_CalcWaveColor -*/ -void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors ) -{ - int i; - int v; - float glow; - int *colors = ( int * ) dstColors; - byte color[4]; - - glow = RB_CalcWaveColorSingle( wf ); - - v = ri.ftol(255 * glow); - color[0] = color[1] = color[2] = v; - color[3] = 255; - v = *(int *)color; - - for ( i = 0; i < tess.numVertexes; i++, colors++ ) { - *colors = v; - } -} - /* ** RB_CalcWaveAlphaSingle */ @@ -754,25 +623,6 @@ float RB_CalcWaveAlphaSingle( const waveForm_t *wf ) return EvalWaveFormClamped( wf ); } -/* -** RB_CalcWaveAlpha -*/ -void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors ) -{ - int i; - int v; - float glow; - - glow = EvalWaveFormClamped( wf ); - - v = 255 * glow; - - for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 ) - { - dstColors[3] = v; - } -} - /* ** RB_CalcModulateColorsByFog */ @@ -793,45 +643,6 @@ void RB_CalcModulateColorsByFog( unsigned char *colors ) { } } -/* -** RB_CalcModulateAlphasByFog -*/ -void RB_CalcModulateAlphasByFog( unsigned char *colors ) { - int i; - float texCoords[SHADER_MAX_VERTEXES][2]; - - // calculate texcoords so we can derive density - // this is not wasted, because it would only have - // been previously called if the surface was opaque - RB_CalcFogTexCoords( texCoords[0] ); - - for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) { - float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] ); - colors[3] *= f; - } -} - -/* -** RB_CalcModulateRGBAsByFog -*/ -void RB_CalcModulateRGBAsByFog( unsigned char *colors ) { - int i; - float texCoords[SHADER_MAX_VERTEXES][2]; - - // calculate texcoords so we can derive density - // this is not wasted, because it would only have - // been previously called if the surface was opaque - RB_CalcFogTexCoords( texCoords[0] ); - - for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) { - float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] ); - colors[0] *= f; - colors[1] *= f; - colors[2] *= f; - colors[3] *= f; - } -} - /* ==================================================================== @@ -928,118 +739,27 @@ void RB_CalcFogTexCoords( float *st ) { } } - - /* -** RB_CalcEnvironmentTexCoords +** RB_CalcTurbulentFactors */ -void RB_CalcEnvironmentTexCoords( float *st ) +void RB_CalcTurbulentFactors( const waveForm_t *wf, float *amplitude, float *now ) { - int i; - float *v, *normal; - vec3_t viewer, reflected; - float d; - - v = tess.xyz[0]; - normal = tess.normal[0]; - - for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 ) - { - VectorSubtract (backEnd.or.viewOrigin, v, viewer); - VectorNormalizeFast (viewer); - - d = DotProduct (normal, viewer); - - reflected[0] = normal[0]*2*d - viewer[0]; - reflected[1] = normal[1]*2*d - viewer[1]; - reflected[2] = normal[2]*2*d - viewer[2]; - - st[0] = 0.5 + reflected[1] * 0.5; - st[1] = 0.5 - reflected[2] * 0.5; - } + *now = wf->phase + tess.shaderTime * wf->frequency; + *amplitude = wf->amplitude; } /* -** RB_CalcTurbulentTexCoords +** RB_CalcScaleTexMatrix */ -void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *st ) -{ - int i; - float now; - - now = ( wf->phase + tess.shaderTime * wf->frequency ); - - for ( i = 0; i < tess.numVertexes; i++, st += 2 ) - { - float s = st[0]; - float t = st[1]; - - st[0] = s + tr.sinTable[ ( ( int ) ( ( ( tess.xyz[i][0] + tess.xyz[i][2] )* 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude; - st[1] = t + tr.sinTable[ ( ( int ) ( ( tess.xyz[i][1] * 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude; - } -} - -void RB_CalcTurbulentTexMatrix( const waveForm_t *wf, matrix_t matrix ) -{ - float now; - - now = ( wf->phase + tess.shaderTime * wf->frequency ); - - // bit of a hack here, hide amplitude and now in the matrix - // the vertex program will extract them and perform a turbulent pass last if it's nonzero - - matrix[ 0] = 1.0f; matrix[ 4] = 0.0f; matrix[ 8] = 0.0f; matrix[12] = wf->amplitude; - matrix[ 1] = 0.0f; matrix[ 5] = 1.0f; matrix[ 9] = 0.0f; matrix[13] = now; - matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f; - matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f; -} - -/* -** RB_CalcScaleTexCoords -*/ -void RB_CalcScaleTexCoords( const float scale[2], float *st ) -{ - int i; - - for ( i = 0; i < tess.numVertexes; i++, st += 2 ) - { - st[0] *= scale[0]; - st[1] *= scale[1]; - } -} - void RB_CalcScaleTexMatrix( const float scale[2], float *matrix ) { - matrix[ 0] = scale[0]; matrix[ 4] = 0.0f; matrix[ 8] = 0.0f; matrix[12] = 0.0f; - matrix[ 1] = 0.0f; matrix[ 5] = scale[1]; matrix[ 9] = 0.0f; matrix[13] = 0.0f; - matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f; - matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f; + matrix[0] = scale[0]; matrix[2] = 0.0f; matrix[4] = 0.0f; + matrix[1] = 0.0f; matrix[3] = scale[1]; matrix[5] = 0.0f; } /* -** RB_CalcScrollTexCoords +** RB_CalcScrollTexMatrix */ -void RB_CalcScrollTexCoords( const float scrollSpeed[2], float *st ) -{ - int i; - float timeScale = tess.shaderTime; - float adjustedScrollS, adjustedScrollT; - - adjustedScrollS = scrollSpeed[0] * timeScale; - adjustedScrollT = scrollSpeed[1] * timeScale; - - // clamp so coordinates don't continuously get larger, causing problems - // with hardware limits - adjustedScrollS = adjustedScrollS - floor( adjustedScrollS ); - adjustedScrollT = adjustedScrollT - floor( adjustedScrollT ); - - for ( i = 0; i < tess.numVertexes; i++, st += 2 ) - { - st[0] += adjustedScrollS; - st[1] += adjustedScrollT; - } -} - void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix ) { float timeScale = tess.shaderTime; @@ -1053,73 +773,28 @@ void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix ) adjustedScrollS = adjustedScrollS - floor( adjustedScrollS ); adjustedScrollT = adjustedScrollT - floor( adjustedScrollT ); - - matrix[ 0] = 1.0f; matrix[ 4] = 0.0f; matrix[ 8] = adjustedScrollS; matrix[12] = 0.0f; - matrix[ 1] = 0.0f; matrix[ 5] = 1.0f; matrix[ 9] = adjustedScrollT; matrix[13] = 0.0f; - matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f; - matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f; + matrix[0] = 1.0f; matrix[2] = 0.0f; matrix[4] = adjustedScrollS; + matrix[1] = 0.0f; matrix[3] = 1.0f; matrix[5] = adjustedScrollT; } /* -** RB_CalcTransformTexCoords +** RB_CalcTransformTexMatrix */ -void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *st ) -{ - int i; - - for ( i = 0; i < tess.numVertexes; i++, st += 2 ) - { - float s = st[0]; - float t = st[1]; - - st[0] = s * tmi->matrix[0][0] + t * tmi->matrix[1][0] + tmi->translate[0]; - st[1] = s * tmi->matrix[0][1] + t * tmi->matrix[1][1] + tmi->translate[1]; - } -} - void RB_CalcTransformTexMatrix( const texModInfo_t *tmi, float *matrix ) { - matrix[ 0] = tmi->matrix[0][0]; matrix[ 4] = tmi->matrix[1][0]; matrix[ 8] = tmi->translate[0]; matrix[12] = 0.0f; - matrix[ 1] = tmi->matrix[0][1]; matrix[ 5] = tmi->matrix[1][1]; matrix[ 9] = tmi->translate[1]; matrix[13] = 0.0f; - matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f; - matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f; + matrix[0] = tmi->matrix[0][0]; matrix[2] = tmi->matrix[1][0]; matrix[4] = tmi->translate[0]; + matrix[1] = tmi->matrix[0][1]; matrix[3] = tmi->matrix[1][1]; matrix[5] = tmi->translate[1]; } /* -** RB_CalcRotateTexCoords +** RB_CalcRotateTexMatrix */ -void RB_CalcRotateTexCoords( float degsPerSecond, float *st ) -{ - float timeScale = tess.shaderTime; - float degs; - int index; - float sinValue, cosValue; - texModInfo_t tmi; - - degs = -degsPerSecond * timeScale; - index = degs * ( FUNCTABLE_SIZE / 360.0f ); - - sinValue = tr.sinTable[ index & FUNCTABLE_MASK ]; - cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ]; - - tmi.matrix[0][0] = cosValue; - tmi.matrix[1][0] = -sinValue; - tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue; - - tmi.matrix[0][1] = sinValue; - tmi.matrix[1][1] = cosValue; - tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue; - - RB_CalcTransformTexCoords( &tmi, st ); -} - void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix ) { float timeScale = tess.shaderTime; float degs; int index; float sinValue, cosValue; - texModInfo_t tmi; degs = -degsPerSecond * timeScale; index = degs * ( FUNCTABLE_SIZE / 360.0f ); @@ -1127,213 +802,6 @@ void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix ) sinValue = tr.sinTable[ index & FUNCTABLE_MASK ]; cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ]; - tmi.matrix[0][0] = cosValue; - tmi.matrix[1][0] = -sinValue; - tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue; - - tmi.matrix[0][1] = sinValue; - tmi.matrix[1][1] = cosValue; - tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue; - - RB_CalcTransformTexMatrix( &tmi, matrix ); + matrix[0] = cosValue; matrix[2] = -sinValue; matrix[4] = 0.5 - 0.5 * cosValue + 0.5 * sinValue; + matrix[1] = sinValue; matrix[3] = cosValue; matrix[5] = 0.5 - 0.5 * sinValue - 0.5 * cosValue; } -/* -** RB_CalcSpecularAlpha -** -** Calculates specular coefficient and places it in the alpha channel -*/ -vec3_t lightOrigin = { -960, 1980, 96 }; // FIXME: track dynamically - -void RB_CalcSpecularAlpha( unsigned char *alphas ) { - int i; - float *v, *normal; - vec3_t viewer, reflected; - float l, d; - int b; - vec3_t lightDir; - int numVertexes; - - v = tess.xyz[0]; - normal = tess.normal[0]; - - alphas += 3; - - numVertexes = tess.numVertexes; - for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4, alphas += 4) { - float ilength; - - VectorSubtract( lightOrigin, v, lightDir ); -// ilength = Q_rsqrt( DotProduct( lightDir, lightDir ) ); - VectorNormalizeFast( lightDir ); - - // calculate the specular color - d = DotProduct (normal, lightDir); -// d *= ilength; - - // we don't optimize for the d < 0 case since this tends to - // cause visual artifacts such as faceted "snapping" - reflected[0] = normal[0]*2*d - lightDir[0]; - reflected[1] = normal[1]*2*d - lightDir[1]; - reflected[2] = normal[2]*2*d - lightDir[2]; - - VectorSubtract (backEnd.or.viewOrigin, v, viewer); - ilength = Q_rsqrt( DotProduct( viewer, viewer ) ); - l = DotProduct (reflected, viewer); - l *= ilength; - - if (l < 0) { - b = 0; - } else { - l = l*l; - l = l*l; - b = l * 255; - if (b > 255) { - b = 255; - } - } - - *alphas = b; - } -} - -/* -** RB_CalcDiffuseColor -** -** The basic vertex lighting calc -*/ -#if idppc_altivec -static void RB_CalcDiffuseColor_altivec( unsigned char *colors ) -{ - int i; - float *v, *normal; - trRefEntity_t *ent; - int ambientLightInt; - vec3_t lightDir; - int numVertexes; - vector unsigned char vSel = VECCONST_UINT8(0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff); - vector float ambientLightVec; - vector float directedLightVec; - vector float lightDirVec; - vector float normalVec0, normalVec1; - vector float incomingVec0, incomingVec1, incomingVec2; - vector float zero, jVec; - vector signed int jVecInt; - vector signed short jVecShort; - vector unsigned char jVecChar, normalPerm; - ent = backEnd.currentEntity; - ambientLightInt = ent->ambientLightInt; - // A lot of this could be simplified if we made sure - // entities light info was 16-byte aligned. - jVecChar = vec_lvsl(0, ent->ambientLight); - ambientLightVec = vec_ld(0, (vector float *)ent->ambientLight); - jVec = vec_ld(11, (vector float *)ent->ambientLight); - ambientLightVec = vec_perm(ambientLightVec,jVec,jVecChar); - - jVecChar = vec_lvsl(0, ent->directedLight); - directedLightVec = vec_ld(0,(vector float *)ent->directedLight); - jVec = vec_ld(11,(vector float *)ent->directedLight); - directedLightVec = vec_perm(directedLightVec,jVec,jVecChar); - - jVecChar = vec_lvsl(0, ent->lightDir); - lightDirVec = vec_ld(0,(vector float *)ent->lightDir); - jVec = vec_ld(11,(vector float *)ent->lightDir); - lightDirVec = vec_perm(lightDirVec,jVec,jVecChar); - - zero = (vector float)vec_splat_s8(0); - VectorCopy( ent->lightDir, lightDir ); - - v = tess.xyz[0]; - normal = tess.normal[0]; - - normalPerm = vec_lvsl(0,normal); - numVertexes = tess.numVertexes; - for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) { - normalVec0 = vec_ld(0,(vector float *)normal); - normalVec1 = vec_ld(11,(vector float *)normal); - normalVec0 = vec_perm(normalVec0,normalVec1,normalPerm); - incomingVec0 = vec_madd(normalVec0, lightDirVec, zero); - incomingVec1 = vec_sld(incomingVec0,incomingVec0,4); - incomingVec2 = vec_add(incomingVec0,incomingVec1); - incomingVec1 = vec_sld(incomingVec1,incomingVec1,4); - incomingVec2 = vec_add(incomingVec2,incomingVec1); - incomingVec0 = vec_splat(incomingVec2,0); - incomingVec0 = vec_max(incomingVec0,zero); - normalPerm = vec_lvsl(12,normal); - jVec = vec_madd(incomingVec0, directedLightVec, ambientLightVec); - jVecInt = vec_cts(jVec,0); // RGBx - jVecShort = vec_pack(jVecInt,jVecInt); // RGBxRGBx - jVecChar = vec_packsu(jVecShort,jVecShort); // RGBxRGBxRGBxRGBx - jVecChar = vec_sel(jVecChar,vSel,vSel); // RGBARGBARGBARGBA replace alpha with 255 - vec_ste((vector unsigned int)jVecChar,0,(unsigned int *)&colors[i*4]); // store color - } -} -#endif - -static void RB_CalcDiffuseColor_scalar( unsigned char *colors ) -{ - int i, j; - float *v, *normal; - float incoming; - trRefEntity_t *ent; - int ambientLightInt; - vec3_t ambientLight; - vec3_t lightDir; - vec3_t directedLight; - int numVertexes; - ent = backEnd.currentEntity; - ambientLightInt = ent->ambientLightInt; - VectorCopy( ent->ambientLight, ambientLight ); - VectorCopy( ent->directedLight, directedLight ); - VectorCopy( ent->lightDir, lightDir ); - - v = tess.xyz[0]; - normal = tess.normal[0]; - - numVertexes = tess.numVertexes; - for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) { - incoming = DotProduct (normal, lightDir); - if ( incoming <= 0 ) { - *(int *)&colors[i*4] = ambientLightInt; - continue; - } - j = ri.ftol(ambientLight[0] + incoming * directedLight[0]); - if ( j > 255 ) { - j = 255; - } - colors[i*4+0] = j; - - j = ri.ftol(ambientLight[1] + incoming * directedLight[1]); - if ( j > 255 ) { - j = 255; - } - colors[i*4+1] = j; - - j = ri.ftol(ambientLight[2] + incoming * directedLight[2]); - if ( j > 255 ) { - j = 255; - } - colors[i*4+2] = j; - - colors[i*4+3] = 255; - } -} - -void RB_CalcDiffuseColor( unsigned char *colors ) -{ -#if idppc_altivec - if (com_altivec->integer) { - // must be in a seperate function or G3 systems will crash. - RB_CalcDiffuseColor_altivec( colors ); - return; - } -#endif - RB_CalcDiffuseColor_scalar( colors ); -} - - - - - diff --git a/code/renderergl2/tr_shader.c b/code/renderergl2/tr_shader.c index 42f235cb..7ff74feb 100644 --- a/code/renderergl2/tr_shader.c +++ b/code/renderergl2/tr_shader.c @@ -2336,6 +2336,7 @@ static qboolean CollapseStagesToGLSL(void) case TCGEN_TEXTURE: case TCGEN_LIGHTMAP: case TCGEN_ENVIRONMENT_MAPPED: + case TCGEN_VECTOR: break; default: skip = qtrue; @@ -2529,6 +2530,7 @@ static qboolean CollapseStagesToGLSL(void) pStage->bundle[TB_LIGHTMAP] = pStage->bundle[TB_DIFFUSEMAP]; pStage->bundle[TB_DIFFUSEMAP].image[0] = tr.whiteImage; pStage->bundle[TB_DIFFUSEMAP].isLightmap = qfalse; + pStage->bundle[TB_DIFFUSEMAP].tcGen = TCGEN_TEXTURE; } } } diff --git a/code/renderergl2/tr_surface.c b/code/renderergl2/tr_surface.c index 06072a82..9f83c7ba 100644 --- a/code/renderergl2/tr_surface.c +++ b/code/renderergl2/tr_surface.c @@ -1621,11 +1621,12 @@ void RB_SurfaceVBOMDVMesh(srfVBOMDVMesh_t * surface) glState.vertexAttribsOldFrame = refEnt->oldframe; glState.vertexAttribsNewFrame = refEnt->frame; + glState.vertexAnimation = qtrue; RB_EndSurface(); // So we don't lerp surfaces that shouldn't be lerped - glState.vertexAttribsInterpolation = 0; + glState.vertexAnimation = qfalse; } static void RB_SurfaceDisplayList( srfDisplayList_t *surf ) { diff --git a/code/renderergl2/tr_vbo.c b/code/renderergl2/tr_vbo.c index e9f2598b..11eb3ceb 100644 --- a/code/renderergl2/tr_vbo.c +++ b/code/renderergl2/tr_vbo.c @@ -608,6 +608,7 @@ void R_BindVBO(VBO_t * vbo) glState.vertexAttribsInterpolation = 0; glState.vertexAttribsOldFrame = 0; glState.vertexAttribsNewFrame = 0; + glState.vertexAnimation = qfalse; qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO); @@ -856,6 +857,9 @@ void RB_UpdateVBOs(unsigned int attribBits) { R_BindVBO(tess.vbo); + // orphan old buffer so we don't stall on it + qglBufferDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->vertexesSize, NULL, GL_DYNAMIC_DRAW_ARB); + if(attribBits & ATTR_BITS) { if(attribBits & ATTR_POSITION) @@ -923,6 +927,9 @@ void RB_UpdateVBOs(unsigned int attribBits) { R_BindIBO(tess.ibo); + // orphan old buffer so we don't stall on it + qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tess.ibo->indexesSize, NULL, GL_DYNAMIC_DRAW_ARB); + qglBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes); } } From 01efe4a53890c102258e061ca9f18b742d127943 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Mon, 14 Oct 2013 03:58:13 -0700 Subject: [PATCH 13/24] OpenGL2: Use an idea from ETXreal and separate world VBO into separate VBOs by shader. --- code/renderergl2/tr_bsp.c | 511 ++++++++++++++++++++---------------- code/renderergl2/tr_local.h | 3 - 2 files changed, 278 insertions(+), 236 deletions(-) diff --git a/code/renderergl2/tr_bsp.c b/code/renderergl2/tr_bsp.c index 3479be1a..7e1d36eb 100644 --- a/code/renderergl2/tr_bsp.c +++ b/code/renderergl2/tr_bsp.c @@ -1831,10 +1831,10 @@ static void CopyVert(const srfVert_t * in, srfVert_t * out) /* =============== -R_CreateWorldVBO +R_CreateWorldVBOs =============== */ -static void R_CreateWorldVBO(void) +static void R_CreateWorldVBOs(void) { int i, j, k; @@ -1844,73 +1844,32 @@ static void R_CreateWorldVBO(void) int numTriangles; srfTriangle_t *triangles; - int numSurfaces; - msurface_t *surface; + int numSortedSurfaces, numSurfaces; + msurface_t *surface, **firstSurf, **lastSurf, **currSurf; msurface_t **surfacesSorted; + VBO_t *vbo; + IBO_t *ibo; + 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++) + // count surfaces + numSortedSurfaces = 0; + for(surface = &s_worldData.surfaces[0]; surface < &s_worldData.surfaces[s_worldData.numsurfaces]; surface++) { - if(*surface->data == SF_FACE) + if(*surface->data == SF_FACE || *surface->data == SF_GRID || *surface->data == SF_TRIANGLES) { - 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++; + numSortedSurfaces++; } } - 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)); + surfacesSorted = ri.Malloc(numSortedSurfaces * sizeof(*surfacesSorted)); j = 0; - for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numsurfaces; k++, surface++) + for(surface = &s_worldData.surfaces[0]; surface < &s_worldData.surfaces[s_worldData.numsurfaces]; surface++) { if(*surface->data == SF_FACE || *surface->data == SF_GRID || *surface->data == SF_TRIANGLES) { @@ -1918,211 +1877,276 @@ static void R_CreateWorldVBO(void) } } - qsort(surfacesSorted, numSurfaces, sizeof(*surfacesSorted), BSPSurfaceCompare); + qsort(surfacesSorted, numSortedSurfaces, sizeof(*surfacesSorted), BSPSurfaceCompare); - // set up triangle indices - numVerts = 0; - numTriangles = 0; - for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k]) + k = 0; + for(firstSurf = lastSurf = surfacesSorted; firstSurf < &surfacesSorted[numSortedSurfaces]; firstSurf = lastSurf) { - if(*surface->data == SF_FACE) + while(lastSurf < &surfacesSorted[numSortedSurfaces] && (*lastSurf)->shader->sortedIndex == (*firstSurf)->shader->sortedIndex) + lastSurf++; + + numVerts = 0; + numTriangles = 0; + numSurfaces = 0; + for (currSurf = firstSurf; currSurf < lastSurf; currSurf++) { - srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data; - - srf->firstIndex = numTriangles * 3; - - if(srf->numTriangles) + surface = *currSurf; + if(*surface->data == SF_FACE) { - srfTriangle_t *tri; + srfSurfaceFace_t *face = (srfSurfaceFace_t *) surface->data; - srf->minIndex = numVerts + srf->triangles->indexes[0]; - srf->maxIndex = numVerts + srf->triangles->indexes[0]; + if(face->numVerts) + numVerts += face->numVerts; - for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++) + 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) + continue; + + ri.Printf(PRINT_ALL, "...calculating world VBO %d ( %i verts %i tris )\n", k, numVerts, numTriangles); + + // create arrays + verts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t)); + triangles = ri.Hunk_AllocateTempMemory(numTriangles * sizeof(srfTriangle_t)); + + // set up triangle indices + numVerts = 0; + numTriangles = 0; + for (currSurf = firstSurf; currSurf < lastSurf; currSurf++) + { + surface = *currSurf; + if(*surface->data == SF_FACE) + { + srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data; + + srf->firstIndex = numTriangles * 3; + + if(srf->numTriangles) { - for(j = 0; j < 3; j++) + srfTriangle_t *tri; + + srf->minIndex = numVerts + srf->triangles->indexes[0]; + srf->maxIndex = numVerts + srf->triangles->indexes[0]; + + for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++) { - triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j]; - srf->minIndex = MIN(srf->minIndex, numVerts + tri->indexes[j]); - srf->maxIndex = MAX(srf->maxIndex, numVerts + tri->indexes[j]); + for(j = 0; j < 3; j++) + { + triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j]; + srf->minIndex = MIN(srf->minIndex, numVerts + tri->indexes[j]); + srf->maxIndex = MAX(srf->maxIndex, numVerts + tri->indexes[j]); + } } + + numTriangles += srf->numTriangles; } - numTriangles += srf->numTriangles; + if(srf->numVerts) + numVerts += srf->numVerts; } - - 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) + else if(*surface->data == SF_GRID) { - srfTriangle_t *tri; + srfGridMesh_t *srf = (srfGridMesh_t *) surface->data; - srf->minIndex = numVerts + srf->triangles->indexes[0]; - srf->maxIndex = numVerts + srf->triangles->indexes[0]; + srf->firstIndex = numTriangles * 3; - for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++) + if(srf->numTriangles) { - for(j = 0; j < 3; j++) + srfTriangle_t *tri; + + srf->minIndex = numVerts + srf->triangles->indexes[0]; + srf->maxIndex = numVerts + srf->triangles->indexes[0]; + + for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++) { - triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j]; - srf->minIndex = MIN(srf->minIndex, numVerts + tri->indexes[j]); - srf->maxIndex = MAX(srf->maxIndex, numVerts + tri->indexes[j]); + for(j = 0; j < 3; j++) + { + triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j]; + srf->minIndex = MIN(srf->minIndex, numVerts + tri->indexes[j]); + srf->maxIndex = MAX(srf->maxIndex, numVerts + tri->indexes[j]); + } } + + numTriangles += srf->numTriangles; } - numTriangles += srf->numTriangles; + if(srf->numVerts) + numVerts += srf->numVerts; } - - 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) + else if(*surface->data == SF_TRIANGLES) { - srfTriangle_t *tri; + srfTriangles_t *srf = (srfTriangles_t *) surface->data; - srf->minIndex = numVerts + srf->triangles->indexes[0]; - srf->maxIndex = numVerts + srf->triangles->indexes[0]; + srf->firstIndex = numTriangles * 3; - for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++) + if(srf->numTriangles) { - for(j = 0; j < 3; j++) + srfTriangle_t *tri; + + srf->minIndex = numVerts + srf->triangles->indexes[0]; + srf->maxIndex = numVerts + srf->triangles->indexes[0]; + + for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++) { - triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j]; - srf->minIndex = MIN(srf->minIndex, numVerts + tri->indexes[j]); - srf->maxIndex = MAX(srf->maxIndex, numVerts + tri->indexes[j]); + for(j = 0; j < 3; j++) + { + triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j]; + srf->minIndex = MIN(srf->minIndex, numVerts + tri->indexes[j]); + srf->maxIndex = MAX(srf->maxIndex, numVerts + tri->indexes[j]); + } } + + numTriangles += srf->numTriangles; } - numTriangles += srf->numTriangles; + if(srf->numVerts) + numVerts += srf->numVerts; } - - 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) + // build vertices + numVerts = 0; + for (currSurf = firstSurf; currSurf < lastSurf; currSurf++) { - srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data; - - srf->firstVert = numVerts; - - if(srf->numVerts) + surface = *currSurf; + if(*surface->data == SF_FACE) { - for(i = 0; i < srf->numVerts; i++) - { - CopyVert(&srf->verts[i], &verts[numVerts + i]); - } + srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data; - numVerts += srf->numVerts; + 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; + } } } - 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); + vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", k), 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); + vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", k), 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); + ibo = R_CreateIBO2(va("staticBspModel0_IBO %i", k), 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) + // point triangle surfaces to VBO + for (currSurf = firstSurf; currSurf < lastSurf; currSurf++) { - srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data; - - if( srf->numVerts && srf->numTriangles) + surface = *currSurf; + if(*surface->data == SF_FACE) { - srf->vbo = s_worldData.vbo; - srf->ibo = s_worldData.ibo; + srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data; + + if( srf->numVerts && srf->numTriangles) + { + srf->vbo = vbo; + srf->ibo = ibo; + } + } + else if(*surface->data == SF_GRID) + { + srfGridMesh_t *srf = (srfGridMesh_t *) surface->data; + + if( srf->numVerts && srf->numTriangles) + { + srf->vbo = vbo; + srf->ibo = ibo; + } + } + else if(*surface->data == SF_TRIANGLES) + { + srfTriangles_t *srf = (srfTriangles_t *) surface->data; + + if( srf->numVerts && srf->numTriangles) + { + srf->vbo = vbo; + srf->ibo = 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; + ri.Hunk_FreeTempMemory(triangles); + ri.Hunk_FreeTempMemory(verts); + + k++; - if( srf->numVerts && srf->numTriangles) - { - srf->vbo = s_worldData.vbo; - srf->ibo = s_worldData.ibo; - } - } } - ri.Free(surfacesSorted); - ri.Hunk_FreeTempMemory(triangles); - ri.Hunk_FreeTempMemory(verts); + endTime = ri.Milliseconds(); + ri.Printf(PRINT_ALL, "world VBOs calculation time = %5.2f seconds\n", (endTime - startTime) / 1000.0); } /* @@ -3006,6 +3030,7 @@ void R_MergeLeafSurfaces(void) int mergedSurfIndex; int numMergedSurfaces; int numUnmergedSurfaces; + VBO_t *vbo; IBO_t *ibo; msurface_t *mergedSurf; @@ -3025,14 +3050,6 @@ void R_MergeLeafSurfaces(void) 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++) { @@ -3166,6 +3183,9 @@ void R_MergeLeafSurfaces(void) s_worldData.viewSurfaces[i] = s_worldData.marksurfaces[i]; } + // need to be synched here + R_IssuePendingRenderCommands(); + // actually merge surfaces numIboIndexes = 0; mergedSurfIndex = 0; @@ -3185,9 +3205,29 @@ void R_MergeLeafSurfaces(void) if (s_worldData.surfacesViewCount[i] != i) continue; - + surf1 = s_worldData.surfaces + i; + // retrieve vbo + switch(*surf1->data) + { + case SF_FACE: + vbo = ((srfSurfaceFace_t *)(surf1->data))->vbo; + break; + + case SF_GRID: + vbo = ((srfGridMesh_t *)(surf1->data))->vbo; + break; + + case SF_TRIANGLES: + vbo = ((srfTriangles_t *)(surf1->data))->vbo; + break; + + default: + vbo = NULL; + break; + } + // count verts, indexes, and surfaces numSurfsToMerge = 0; numTriangles = 0; @@ -3245,6 +3285,15 @@ void R_MergeLeafSurfaces(void) continue; } + // create ibo + ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low); + memset(ibo, 0, sizeof(*ibo)); + Q_strncpyz(ibo->name, va("staticWorldMesh_IBO_mergedSurfs%i", tr.numIBOs++), sizeof(ibo->name)); + numIboIndexes = 0; + + // allocate indexes + iboIndexes = outIboIndexes = ri.Malloc(numTriangles * 3 * sizeof(*outIboIndexes)); + // Merge surfaces (indexes) and calculate bounds ClearBounds(bounds[0], bounds[1]); firstIndex = numIboIndexes; @@ -3320,7 +3369,7 @@ void R_MergeLeafSurfaces(void) memset(vboSurf, 0, sizeof(*vboSurf)); vboSurf->surfaceType = SF_VBO_MESH; - vboSurf->vbo = s_worldData.vbo; + vboSurf->vbo = vbo; vboSurf->ibo = ibo; vboSurf->numIndexes = numTriangles * 3; @@ -3352,6 +3401,17 @@ void R_MergeLeafSurfaces(void) mergedSurf->cubemapIndex = surf1->cubemapIndex; mergedSurf->shader = surf1->shader; + // finish up the ibo + 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); + // redirect view surfaces to this surf for (j = 0; j < numWorldSurfaces; j++) { @@ -3372,21 +3432,6 @@ void R_MergeLeafSurfaces(void) mergedSurf++; } - // finish up the ibo - R_IssuePendingRenderCommands(); - - 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", @@ -3743,7 +3788,7 @@ void RE_LoadWorldMap( const char *name ) { } // create static VBOS from the world - R_CreateWorldVBO(); + R_CreateWorldVBOs(); if (r_mergeLeafSurfaces->integer) { R_MergeLeafSurfaces(); diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index 82fbb004..7d39b65c 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -1334,9 +1334,6 @@ typedef struct { int numDecisionNodes; mnode_t *nodes; - VBO_t *vbo; - IBO_t *ibo; - int numWorldSurfaces; int numsurfaces; From 535d0ea70eb52f07a43b0c283cd66456472d85bd Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Tue, 15 Oct 2013 01:19:16 -0700 Subject: [PATCH 14/24] OpenGL2: Merge bsp surface structs into a single struct, and more cleanup. --- code/renderergl2/tr_bsp.c | 455 ++++++++++------------------------ code/renderergl2/tr_curve.c | 36 ++- code/renderergl2/tr_light.c | 17 +- code/renderergl2/tr_local.h | 168 +++---------- code/renderergl2/tr_main.c | 99 +------- code/renderergl2/tr_marks.c | 12 +- code/renderergl2/tr_model.c | 2 - code/renderergl2/tr_surface.c | 10 +- code/renderergl2/tr_world.c | 44 ++-- 9 files changed, 227 insertions(+), 616 deletions(-) diff --git a/code/renderergl2/tr_bsp.c b/code/renderergl2/tr_bsp.c index 7e1d36eb..275fdf83 100644 --- a/code/renderergl2/tr_bsp.c +++ b/code/renderergl2/tr_bsp.c @@ -652,7 +652,7 @@ ParseFace */ static void ParseFace( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf, int *indexes ) { int i, j; - srfSurfaceFace_t *cv; + srfBspSurface_t *cv; srfTriangle_t *tri; int numVerts, numTriangles, badTriangles; int realLightmapNum; @@ -767,12 +767,12 @@ static void ParseFace( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, // take the plane information from the lightmap vector for ( i = 0 ; i < 3 ; i++ ) { - cv->plane.normal[i] = LittleFloat( ds->lightmapVecs[2][i] ); + cv->cullPlane.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; + cv->cullPlane.dist = DotProduct( cv->verts[0].xyz, cv->cullPlane.normal ); + SetPlaneSignbits( &cv->cullPlane ); + cv->cullPlane.type = PlaneTypeForNormal( cv->cullPlane.normal ); + surf->cullinfo.plane = cv->cullPlane; surf->data = (surfaceType_t *)cv; @@ -800,7 +800,7 @@ ParseMesh =============== */ static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf ) { - srfGridMesh_t *grid; + srfBspSurface_t *grid; int i, j; int width, height, numPoints; srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE]; @@ -903,7 +903,7 @@ ParseTriSurf =============== */ static void ParseTriSurf( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf, int *indexes ) { - srfTriangles_t *cv; + srfBspSurface_t *cv; srfTriangle_t *tri; int i, j; int numVerts, numTriangles, badTriangles; @@ -1065,7 +1065,7 @@ R_MergedWidthPoints returns true if there are grid points merged on a width edge ================= */ -int R_MergedWidthPoints(srfGridMesh_t *grid, int offset) { +int R_MergedWidthPoints(srfBspSurface_t *grid, int offset) { int i, j; for (i = 1; i < grid->width-1; i++) { @@ -1086,7 +1086,7 @@ R_MergedHeightPoints returns true if there are grid points merged on a height edge ================= */ -int R_MergedHeightPoints(srfGridMesh_t *grid, int offset) { +int R_MergedHeightPoints(srfBspSurface_t *grid, int offset) { int i, j; for (i = 1; i < grid->height-1; i++) { @@ -1109,13 +1109,13 @@ 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 ) { +void R_FixSharedVertexLodError_r( int start, srfBspSurface_t *grid1 ) { int j, k, l, m, n, offset1, offset2, touch; - srfGridMesh_t *grid2; + srfBspSurface_t *grid2; for ( j = start; j < s_worldData.numsurfaces; j++ ) { // - grid2 = (srfGridMesh_t *) s_worldData.surfaces[j].data; + grid2 = (srfBspSurface_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 @@ -1223,11 +1223,11 @@ If this is not the case this function will still do its job but won't fix the hi */ void R_FixSharedVertexLodError( void ) { int i; - srfGridMesh_t *grid1; + srfBspSurface_t *grid1; for ( i = 0; i < s_worldData.numsurfaces; i++ ) { // - grid1 = (srfGridMesh_t *) s_worldData.surfaces[i].data; + grid1 = (srfBspSurface_t *) s_worldData.surfaces[i].data; // if this surface is not a grid if ( grid1->surfaceType != SF_GRID ) continue; @@ -1249,11 +1249,11 @@ R_StitchPatches */ int R_StitchPatches( int grid1num, int grid2num ) { float *v1, *v2; - srfGridMesh_t *grid1, *grid2; + srfBspSurface_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; + grid1 = (srfBspSurface_t *) s_worldData.surfaces[grid1num].data; + grid2 = (srfBspSurface_t *) s_worldData.surfaces[grid2num].data; for (n = 0; n < 2; n++) { // if (n) offset1 = (grid1->height-1) * grid1->width; @@ -1664,13 +1664,13 @@ might still appear at that side. */ int R_TryStitchingPatch( int grid1num ) { int j, numstitches; - srfGridMesh_t *grid1, *grid2; + srfBspSurface_t *grid1, *grid2; numstitches = 0; - grid1 = (srfGridMesh_t *) s_worldData.surfaces[grid1num].data; + grid1 = (srfBspSurface_t *) s_worldData.surfaces[grid1num].data; for ( j = 0; j < s_worldData.numsurfaces; j++ ) { // - grid2 = (srfGridMesh_t *) s_worldData.surfaces[j].data; + grid2 = (srfBspSurface_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 @@ -1695,7 +1695,7 @@ R_StitchAllPatches */ void R_StitchAllPatches( void ) { int i, stitched, numstitches; - srfGridMesh_t *grid1; + srfBspSurface_t *grid1; numstitches = 0; do @@ -1703,7 +1703,7 @@ void R_StitchAllPatches( void ) { stitched = qfalse; for ( i = 0; i < s_worldData.numsurfaces; i++ ) { // - grid1 = (srfGridMesh_t *) s_worldData.surfaces[i].data; + grid1 = (srfBspSurface_t *) s_worldData.surfaces[i].data; // if this surface is not a grid if ( grid1->surfaceType != SF_GRID ) continue; @@ -1728,11 +1728,11 @@ R_MovePatchSurfacesToHunk */ void R_MovePatchSurfacesToHunk(void) { int i, size; - srfGridMesh_t *grid, *hunkgrid; + srfBspSurface_t *grid, *hunkgrid; for ( i = 0; i < s_worldData.numsurfaces; i++ ) { // - grid = (srfGridMesh_t *) s_worldData.surfaces[i].data; + grid = (srfBspSurface_t *) s_worldData.surfaces[i].data; // if this surface is not a grid if ( grid->surfaceType != SF_GRID ) continue; @@ -1890,42 +1890,24 @@ static void R_CreateWorldVBOs(void) numSurfaces = 0; for (currSurf = firstSurf; currSurf < lastSurf; currSurf++) { - surface = *currSurf; - if(*surface->data == SF_FACE) + srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data; + + switch (bspSurf->surfaceType) { - srfSurfaceFace_t *face = (srfSurfaceFace_t *) surface->data; + case SF_FACE: + case SF_GRID: + case SF_TRIANGLES: + if(bspSurf->numVerts) + numVerts += bspSurf->numVerts; - if(face->numVerts) - numVerts += face->numVerts; + if(bspSurf->numTriangles) + numTriangles += bspSurf->numTriangles; - if(face->numTriangles) - numTriangles += face->numTriangles; + numSurfaces++; + break; - 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++; + default: + break; } } @@ -1943,93 +1925,42 @@ static void R_CreateWorldVBOs(void) numTriangles = 0; for (currSurf = firstSurf; currSurf < lastSurf; currSurf++) { - surface = *currSurf; - if(*surface->data == SF_FACE) + srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data; + + switch (bspSurf->surfaceType) { - srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data; + case SF_FACE: + case SF_GRID: + case SF_TRIANGLES: + bspSurf->firstIndex = numTriangles * 3; - srf->firstIndex = numTriangles * 3; - - if(srf->numTriangles) - { - srfTriangle_t *tri; - - srf->minIndex = numVerts + srf->triangles->indexes[0]; - srf->maxIndex = numVerts + srf->triangles->indexes[0]; - - for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++) + if(bspSurf->numTriangles) { - for(j = 0; j < 3; j++) + srfTriangle_t *tri; + + bspSurf->minIndex = numVerts + bspSurf->triangles->indexes[0]; + bspSurf->maxIndex = numVerts + bspSurf->triangles->indexes[0]; + + for(i = 0, tri = bspSurf->triangles; i < bspSurf->numTriangles; i++, tri++) { - triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j]; - srf->minIndex = MIN(srf->minIndex, numVerts + tri->indexes[j]); - srf->maxIndex = MAX(srf->maxIndex, numVerts + tri->indexes[j]); + for(j = 0; j < 3; j++) + { + triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j]; + bspSurf->minIndex = MIN(bspSurf->minIndex, numVerts + tri->indexes[j]); + bspSurf->maxIndex = MAX(bspSurf->maxIndex, numVerts + tri->indexes[j]); + } } + + numTriangles += bspSurf->numTriangles; } - numTriangles += srf->numTriangles; - } + if(bspSurf->numVerts) + numVerts += bspSurf->numVerts; - if(srf->numVerts) - numVerts += srf->numVerts; - } - else if(*surface->data == SF_GRID) - { - srfGridMesh_t *srf = (srfGridMesh_t *) surface->data; + break; - srf->firstIndex = numTriangles * 3; - - if(srf->numTriangles) - { - srfTriangle_t *tri; - - srf->minIndex = numVerts + srf->triangles->indexes[0]; - srf->maxIndex = numVerts + srf->triangles->indexes[0]; - - 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]; - srf->minIndex = MIN(srf->minIndex, numVerts + tri->indexes[j]); - srf->maxIndex = MAX(srf->maxIndex, 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; - - srf->minIndex = numVerts + srf->triangles->indexes[0]; - srf->maxIndex = numVerts + srf->triangles->indexes[0]; - - 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]; - srf->minIndex = MIN(srf->minIndex, numVerts + tri->indexes[j]); - srf->maxIndex = MAX(srf->maxIndex, numVerts + tri->indexes[j]); - } - } - - numTriangles += srf->numTriangles; - } - - if(srf->numVerts) - numVerts += srf->numVerts; + default: + break; } } @@ -2037,54 +1968,29 @@ static void R_CreateWorldVBOs(void) numVerts = 0; for (currSurf = firstSurf; currSurf < lastSurf; currSurf++) { - surface = *currSurf; - if(*surface->data == SF_FACE) + srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data; + + switch (bspSurf->surfaceType) { - srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data; + case SF_FACE: + case SF_GRID: + case SF_TRIANGLES: + bspSurf->firstVert = numVerts; - srf->firstVert = numVerts; - - if(srf->numVerts) - { - for(i = 0; i < srf->numVerts; i++) + if(bspSurf->numVerts) { - CopyVert(&srf->verts[i], &verts[numVerts + i]); + for(i = 0; i < bspSurf->numVerts; i++) + { + CopyVert(&bspSurf->verts[i], &verts[numVerts + i]); + } + + numVerts += bspSurf->numVerts; } - numVerts += srf->numVerts; - } - } - else if(*surface->data == SF_GRID) - { - srfGridMesh_t *srf = (srfGridMesh_t *) surface->data; + break; - 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; - } + default: + break; } } @@ -2103,36 +2009,23 @@ static void R_CreateWorldVBOs(void) // point triangle surfaces to VBO for (currSurf = firstSurf; currSurf < lastSurf; currSurf++) { - surface = *currSurf; - if(*surface->data == SF_FACE) - { - srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data; + srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data; - if( srf->numVerts && srf->numTriangles) - { - srf->vbo = vbo; - srf->ibo = ibo; - } - } - else if(*surface->data == SF_GRID) + switch (bspSurf->surfaceType) { - srfGridMesh_t *srf = (srfGridMesh_t *) surface->data; + case SF_FACE: + case SF_GRID: + case SF_TRIANGLES: + if( bspSurf->numVerts && bspSurf->numTriangles) + { + bspSurf->vbo = vbo; + bspSurf->ibo = ibo; + } - if( srf->numVerts && srf->numTriangles) - { - srf->vbo = vbo; - srf->ibo = ibo; - } - } - else if(*surface->data == SF_TRIANGLES) - { - srfTriangles_t *srf = (srfTriangles_t *) surface->data; + break; - if( srf->numVerts && srf->numTriangles) - { - srf->vbo = vbo; - srf->ibo = ibo; - } + default: + break; } } @@ -2220,10 +2113,10 @@ static void R_LoadSurfaces( lump_t *surfs, lump_t *verts, lump_t *indexLump ) { // FIXME: do this break; case MST_TRIANGLE_SOUP: - out->data = ri.Hunk_Alloc( sizeof(srfTriangles_t), h_low); + out->data = ri.Hunk_Alloc( sizeof(srfBspSurface_t), h_low); break; case MST_PLANAR: - out->data = ri.Hunk_Alloc( sizeof(srfSurfaceFace_t), h_low); + out->data = ri.Hunk_Alloc( sizeof(srfBspSurface_t), h_low); break; case MST_FLARE: out->data = ri.Hunk_Alloc( sizeof(srfFlare_t), h_low); @@ -2240,13 +2133,13 @@ static void R_LoadSurfaces( lump_t *surfs, lump_t *verts, lump_t *indexLump ) { case MST_PATCH: ParseMesh ( in, dv, hdrVertColors, out ); { - srfGridMesh_t *surface = (srfGridMesh_t *)out->data; + srfBspSurface_t *surface = (srfBspSurface_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; + VectorCopy(surface->cullBounds[0], out->cullinfo.bounds[0]); + VectorCopy(surface->cullBounds[1], out->cullinfo.bounds[1]); + VectorCopy(surface->cullOrigin, out->cullinfo.localOrigin); + out->cullinfo.radius = surface->cullRadius; } numMeshes++; break; @@ -3201,7 +3094,7 @@ void R_MergeLeafSurfaces(void) int numVerts; int firstIndex; - srfVBOMesh_t *vboSurf; + srfBspSurface_t *vboSurf; if (s_worldData.surfacesViewCount[i] != i) continue; @@ -3212,15 +3105,9 @@ void R_MergeLeafSurfaces(void) switch(*surf1->data) { case SF_FACE: - vbo = ((srfSurfaceFace_t *)(surf1->data))->vbo; - break; - case SF_GRID: - vbo = ((srfGridMesh_t *)(surf1->data))->vbo; - break; - case SF_TRIANGLES: - vbo = ((srfTriangles_t *)(surf1->data))->vbo; + vbo = ((srfBspSurface_t *)(surf1->data))->vbo; break; default: @@ -3235,42 +3122,21 @@ void R_MergeLeafSurfaces(void) for (j = 0; j < numWorldSurfaces; j++) { msurface_t *surf2; + srfBspSurface_t *bspSurf; if (s_worldData.surfacesViewCount[j] != i) continue; surf2 = s_worldData.surfaces + j; - switch(*surf2->data) + bspSurf = (srfBspSurface_t *) surf2->data; + switch(bspSurf->surfaceType) { 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; - } + numTriangles += bspSurf->numTriangles; + numVerts += bspSurf->numVerts; break; default: @@ -3300,6 +3166,7 @@ void R_MergeLeafSurfaces(void) for (j = 0; j < numWorldSurfaces; j++) { msurface_t *surf2; + srfBspSurface_t *bspSurf; if (s_worldData.surfacesViewCount[j] != i) continue; @@ -3309,53 +3176,18 @@ void R_MergeLeafSurfaces(void) AddPointToBounds(surf2->cullinfo.bounds[0], bounds[0], bounds[1]); AddPointToBounds(surf2->cullinfo.bounds[1], bounds[0], bounds[1]); - switch(*surf2->data) + bspSurf = (srfBspSurface_t *) surf2->data; + switch(bspSurf->surfaceType) { 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: + for (k = 0; k < bspSurf->numTriangles; k++) { - 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; - } + *outIboIndexes++ = bspSurf->triangles[k].indexes[0] + bspSurf->firstVert; + *outIboIndexes++ = bspSurf->triangles[k].indexes[1] + bspSurf->firstVert; + *outIboIndexes++ = bspSurf->triangles[k].indexes[2] + bspSurf->firstVert; + numIboIndexes += 3; } break; @@ -3372,7 +3204,7 @@ void R_MergeLeafSurfaces(void) vboSurf->vbo = vbo; vboSurf->ibo = ibo; - vboSurf->numIndexes = numTriangles * 3; + vboSurf->numTriangles = numTriangles; vboSurf->numVerts = numVerts; vboSurf->firstIndex = firstIndex; @@ -3385,12 +3217,8 @@ void R_MergeLeafSurfaces(void) vboSurf->maxIndex = MAX(vboSurf->maxIndex, *(iboIndexes + firstIndex + j)); } - vboSurf->shader = surf1->shader; - vboSurf->fogIndex = surf1->fogIndex; - vboSurf->cubemapIndex = surf1->cubemapIndex; - - VectorCopy(bounds[0], vboSurf->bounds[0]); - VectorCopy(bounds[1], vboSurf->bounds[1]); + VectorCopy(bounds[0], vboSurf->cullBounds[0]); + VectorCopy(bounds[1], vboSurf->cullBounds[1]); VectorCopy(bounds[0], mergedSurf->cullinfo.bounds[0]); VectorCopy(bounds[1], mergedSurf->cullinfo.bounds[1]); @@ -3452,41 +3280,20 @@ void R_CalcVertexLightDirs( void ) 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; + srfBspSurface_t *bspSurf = (srfBspSurface_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) + switch(bspSurf->surfaceType) { - srfGridMesh_t *srf = (srfGridMesh_t *) surface->data; + case SF_FACE: + case SF_GRID: + case SF_TRIANGLES: + for(i = 0; i < bspSurf->numVerts; i++) + R_LightDirForPoint( bspSurf->verts[i].xyz, bspSurf->verts[i].lightdir, bspSurf->verts[i].normal, &s_worldData ); - 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; + break; - 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 ); - } - } + default: + break; } } } diff --git a/code/renderergl2/tr_curve.c b/code/renderergl2/tr_curve.c index 3d439257..e9414159 100644 --- a/code/renderergl2/tr_curve.c +++ b/code/renderergl2/tr_curve.c @@ -25,14 +25,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /* This file does all of the processing necessary to turn a raw grid of points -read from the map file into a srfGridMesh_t ready for rendering. +read from the map file into a srfBspSurface_t ready for rendering. The level of detail solution is direction independent, based only on subdivided distance from the true curve. Only a single entry point: -srfGridMesh_t *R_SubdividePatchToGrid( int width, int height, +srfBspSurface_t *R_SubdividePatchToGrid( int width, int height, srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) { */ @@ -329,8 +329,6 @@ static int MakeMeshTriangles(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE } } - R_CalcSurfaceTriangleNeighbors(numTriangles, triangles); - // FIXME: use more elegant way for(i = 0; i < width; i++) { @@ -341,8 +339,6 @@ static int MakeMeshTriangles(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE } } - R_CalcSurfaceTrianglePlanes(numTriangles, triangles, ctrl2); - return numTriangles; } @@ -420,13 +416,13 @@ static void PutPointsOnCurve( srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], R_CreateSurfaceGridMesh ================= */ -srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height, +srfBspSurface_t *R_CreateSurfaceGridMesh(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], float errorTable[2][MAX_GRID_SIZE], int numTriangles, srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2]) { int i, j, size; srfVert_t *vert; vec3_t tmpVec; - srfGridMesh_t *grid; + srfBspSurface_t *grid; // copy the results out to a grid size = (width * height - 1) * sizeof( srfVert_t ) + sizeof( *grid ); @@ -468,23 +464,23 @@ srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height, grid->width = width; grid->height = height; grid->surfaceType = SF_GRID; - ClearBounds( grid->meshBounds[0], grid->meshBounds[1] ); + ClearBounds( grid->cullBounds[0], grid->cullBounds[1] ); for ( i = 0 ; i < width ; i++ ) { for ( j = 0 ; j < height ; j++ ) { vert = &grid->verts[j*width+i]; *vert = ctrl[j][i]; - AddPointToBounds( vert->xyz, grid->meshBounds[0], grid->meshBounds[1] ); + AddPointToBounds( vert->xyz, grid->cullBounds[0], grid->cullBounds[1] ); } } // compute local origin and bounds - VectorAdd( grid->meshBounds[0], grid->meshBounds[1], grid->localOrigin ); - VectorScale( grid->localOrigin, 0.5f, grid->localOrigin ); - VectorSubtract( grid->meshBounds[0], grid->localOrigin, tmpVec ); - grid->meshRadius = VectorLength( tmpVec ); + VectorAdd( grid->cullBounds[0], grid->cullBounds[1], grid->cullOrigin ); + VectorScale( grid->cullOrigin, 0.5f, grid->cullOrigin ); + VectorSubtract( grid->cullBounds[0], grid->cullOrigin, tmpVec ); + grid->cullRadius = VectorLength( tmpVec ); - VectorCopy( grid->localOrigin, grid->lodOrigin ); - grid->lodRadius = grid->meshRadius; + VectorCopy( grid->cullOrigin, grid->lodOrigin ); + grid->lodRadius = grid->cullRadius; // return grid; } @@ -494,7 +490,7 @@ srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height, R_FreeSurfaceGridMesh ================= */ -void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ) { +void R_FreeSurfaceGridMesh( srfBspSurface_t *grid ) { ri.Free(grid->widthLodError); ri.Free(grid->heightLodError); ri.Free(grid->triangles); @@ -507,7 +503,7 @@ void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ) { R_SubdividePatchToGrid ================= */ -srfGridMesh_t *R_SubdividePatchToGrid( int width, int height, +srfBspSurface_t *R_SubdividePatchToGrid( int width, int height, srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) { int i, j, k, l; srfVert_t_cleared( prev ); @@ -690,7 +686,7 @@ srfGridMesh_t *R_SubdividePatchToGrid( int width, int height, R_GridInsertColumn =============== */ -srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ) { +srfBspSurface_t *R_GridInsertColumn( srfBspSurface_t *grid, int column, int row, vec3_t point, float loderror ) { int i, j; int width, height, oldwidth; srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; @@ -750,7 +746,7 @@ srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec R_GridInsertRow =============== */ -srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ) { +srfBspSurface_t *R_GridInsertRow( srfBspSurface_t *grid, int row, int column, vec3_t point, float loderror ) { int i, j; int width, height, oldheight; srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; diff --git a/code/renderergl2/tr_light.c b/code/renderergl2/tr_light.c index dc5a05d9..3d1d1f24 100644 --- a/code/renderergl2/tr_light.c +++ b/code/renderergl2/tr_light.c @@ -94,12 +94,17 @@ void R_DlightBmodel( bmodel_t *bmodel ) { for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) { surf = tr.world->surfaces + bmodel->firstSurface + i; - if ( *surf->data == SF_FACE ) { - ((srfSurfaceFace_t *)surf->data)->dlightBits = mask; - } else if ( *surf->data == SF_GRID ) { - ((srfGridMesh_t *)surf->data)->dlightBits = mask; - } else if ( *surf->data == SF_TRIANGLES ) { - ((srfTriangles_t *)surf->data)->dlightBits = mask; + switch(*surf->data) + { + case SF_FACE: + case SF_GRID: + case SF_TRIANGLES: + case SF_VBO_MESH: + ((srfBspSurface_t *)surf->data)->dlightBits = mask; + break; + + default: + break; } } } diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index 7d39b65c..261f016c 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -1028,13 +1028,10 @@ typedef struct { int indexes[3]; int neighbors[3]; - vec4_t plane; - qboolean facingLight; - qboolean degenerated; } srfTriangle_t; - -typedef struct srfGridMesh_s +// srfBspSurface_t covers SF_GRID, SF_TRIANGLES, SF_POLY, and SF_VBO_MESH +typedef struct srfBspSurface_s { surfaceType_t surfaceType; @@ -1043,9 +1040,30 @@ typedef struct srfGridMesh_s int pshadowBits; // culling information - vec3_t meshBounds[2]; - vec3_t localOrigin; - float meshRadius; + vec3_t cullBounds[2]; + vec3_t cullOrigin; + float cullRadius; + cplane_t cullPlane; + + // triangle definitions + int numTriangles; + srfTriangle_t *triangles; + + // vertexes + int numVerts; + srfVert_t *verts; + + // BSP VBO offsets + int firstVert; + int firstIndex; + glIndex_t minIndex; + glIndex_t maxIndex; + + // static render data + VBO_t *vbo; + IBO_t *ibo; + + // SF_GRID specific variables after here // lod information, which may be different // than the culling information to allow for @@ -1059,85 +1077,7 @@ typedef struct srfGridMesh_s int width, height; float *widthLodError; float *heightLodError; - - int numTriangles; - srfTriangle_t *triangles; - - int numVerts; - srfVert_t *verts; - - // BSP VBO offsets - int firstVert; - int firstIndex; - glIndex_t minIndex; - glIndex_t maxIndex; - - // static render data - VBO_t *vbo; // points to bsp model VBO - IBO_t *ibo; -} srfGridMesh_t; - - -typedef struct -{ - surfaceType_t surfaceType; - - // dynamic lighting information - int dlightBits; - int pshadowBits; - - // culling information - cplane_t plane; -// vec3_t bounds[2]; - - // triangle definitions - int numTriangles; - srfTriangle_t *triangles; - - int numVerts; - srfVert_t *verts; - - // BSP VBO offsets - int firstVert; - int firstIndex; - glIndex_t minIndex; - glIndex_t maxIndex; - - // static render data - VBO_t *vbo; // points to bsp model VBO - IBO_t *ibo; -} srfSurfaceFace_t; - - -// misc_models in maps are turned into direct geometry by xmap -typedef struct -{ - surfaceType_t surfaceType; - - // dynamic lighting information - int dlightBits; - int pshadowBits; - - // culling information -// vec3_t bounds[2]; - - // triangle definitions - int numTriangles; - srfTriangle_t *triangles; - - int numVerts; - srfVert_t *verts; - - // BSP VBO offsets - int firstVert; - int firstIndex; - glIndex_t minIndex; - glIndex_t maxIndex; - - // static render data - VBO_t *vbo; // points to bsp model VBO - IBO_t *ibo; -} srfTriangles_t; +} srfBspSurface_t; // inter-quake-model typedef struct { @@ -1174,33 +1114,6 @@ typedef struct srfIQModel_s { int first_triangle, num_triangles; } srfIQModel_t; -typedef struct srfVBOMesh_s -{ - surfaceType_t surfaceType; - - struct shader_s *shader; // FIXME move this to somewhere else - int fogIndex; - int cubemapIndex; - - // dynamic lighting information - int dlightBits; - int pshadowBits; - - // culling information - vec3_t bounds[2]; - - // backEnd stats - int numIndexes; - int numVerts; - int firstIndex; - glIndex_t minIndex; - glIndex_t maxIndex; - - // static render data - VBO_t *vbo; - IBO_t *ibo; -} srfVBOMesh_t; - typedef struct srfVBOMDVMesh_s { surfaceType_t surfaceType; @@ -2054,8 +1967,6 @@ void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal, const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2); qboolean R_CalcTangentVectors(srfVert_t * dv[3]); -void R_CalcSurfaceTriangleNeighbors(int numTriangles, srfTriangle_t * triangles); -void R_CalcSurfaceTrianglePlanes(int numTriangles, srfTriangle_t * triangles, srfVert_t * verts); #define CULL_IN 0 // completely unclipped #define CULL_CLIP 1 // clipped by one or more planes @@ -2350,11 +2261,11 @@ CURVE TESSELATION #define PATCH_STITCHING -srfGridMesh_t *R_SubdividePatchToGrid( int width, int height, +srfBspSurface_t *R_SubdividePatchToGrid( int width, int height, srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ); -srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ); -srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ); -void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ); +srfBspSurface_t *R_GridInsertColumn( srfBspSurface_t *grid, int column, int row, vec3_t point, float loderror ); +srfBspSurface_t *R_GridInsertRow( srfBspSurface_t *grid, int row, int column, vec3_t point, float loderror ); +void R_FreeSurfaceGridMesh( srfBspSurface_t *grid ); /* ============================================================ @@ -2501,13 +2412,7 @@ void R_TransformClipToWindow( const vec4_t clip, const viewParms_t *view, vec4_t void RB_DeformTessGeometry( void ); -void RB_CalcEnvironmentTexCoords( float *dstTexCoords ); void RB_CalcFogTexCoords( float *dstTexCoords ); -void RB_CalcScrollTexCoords( const float scroll[2], float *dstTexCoords ); -void RB_CalcRotateTexCoords( float rotSpeed, float *dstTexCoords ); -void RB_CalcScaleTexCoords( const float scale[2], float *dstTexCoords ); -void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *dstTexCoords ); -void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *dstTexCoords ); void RB_CalcScaleTexMatrix( const float scale[2], float *matrix ); void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix ); @@ -2517,19 +2422,8 @@ 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 ); /* ============================================================= diff --git a/code/renderergl2/tr_main.c b/code/renderergl2/tr_main.c index 9899432b..37993d4d 100644 --- a/code/renderergl2/tr_main.c +++ b/code/renderergl2/tr_main.c @@ -492,99 +492,6 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3]) #endif -/* -================= -R_FindSurfaceTriangleWithEdge - -Recoded from Q2E -================= -*/ -static int R_FindSurfaceTriangleWithEdge(int numTriangles, srfTriangle_t * triangles, int start, int end, int ignore) -{ - srfTriangle_t *tri; - int count, match; - int i; - - count = 0; - match = -1; - - for(i = 0, tri = triangles; i < numTriangles; i++, tri++) - { - if((tri->indexes[0] == start && tri->indexes[1] == end) || - (tri->indexes[1] == start && tri->indexes[2] == end) || (tri->indexes[2] == start && tri->indexes[0] == end)) - { - if(i != ignore) - { - match = i; - } - - count++; - } - else if((tri->indexes[1] == start && tri->indexes[0] == end) || - (tri->indexes[2] == start && tri->indexes[1] == end) || (tri->indexes[0] == start && tri->indexes[2] == end)) - { - count++; - } - } - - // detect edges shared by three triangles and make them seams - if(count > 2) - { - match = -1; - } - - return match; -} - - -/* -================= -R_CalcSurfaceTriangleNeighbors - -Recoded from Q2E -================= -*/ -void R_CalcSurfaceTriangleNeighbors(int numTriangles, srfTriangle_t * triangles) -{ - int i; - srfTriangle_t *tri; - - for(i = 0, tri = triangles; i < numTriangles; i++, tri++) - { - tri->neighbors[0] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[1], tri->indexes[0], i); - tri->neighbors[1] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[2], tri->indexes[1], i); - tri->neighbors[2] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[0], tri->indexes[2], i); - } -} - -/* -================= -R_CalcSurfaceTrianglePlanes -================= -*/ -void R_CalcSurfaceTrianglePlanes(int numTriangles, srfTriangle_t * triangles, srfVert_t * verts) -{ - int i; - srfTriangle_t *tri; - - for(i = 0, tri = triangles; i < numTriangles; i++, tri++) - { - float *v1, *v2, *v3; - vec3_t d1, d2; - - v1 = verts[tri->indexes[0]].xyz; - v2 = verts[tri->indexes[1]].xyz; - v3 = verts[tri->indexes[2]].xyz; - - VectorSubtract(v2, v1, d1); - VectorSubtract(v3, v1, d2); - - CrossProduct(d2, d1, tri->plane); - tri->plane[3] = DotProduct(tri->plane, v1); - } -} - - /* ================= R_CullLocalBox @@ -1365,7 +1272,7 @@ R_PlaneForSurface ============= */ void R_PlaneForSurface (surfaceType_t *surfType, cplane_t *plane) { - srfTriangles_t *tri; + srfBspSurface_t *tri; srfPoly_t *poly; srfVert_t *v1, *v2, *v3; vec4_t plane4; @@ -1377,10 +1284,10 @@ void R_PlaneForSurface (surfaceType_t *surfType, cplane_t *plane) { } switch (*surfType) { case SF_FACE: - *plane = ((srfSurfaceFace_t *)surfType)->plane; + *plane = ((srfBspSurface_t *)surfType)->cullPlane; return; case SF_TRIANGLES: - tri = (srfTriangles_t *)surfType; + tri = (srfBspSurface_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]; diff --git a/code/renderergl2/tr_marks.c b/code/renderergl2/tr_marks.c index 4d070565..dc625102 100644 --- a/code/renderergl2/tr_marks.c +++ b/code/renderergl2/tr_marks.c @@ -268,7 +268,7 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio vec3_t clipPoints[2][MAX_VERTS_ON_POLY]; int numClipPoints; float *v; - srfGridMesh_t *cv; + srfBspSurface_t *cv; srfTriangle_t *tri; srfVert_t *dv; vec3_t normal; @@ -327,7 +327,7 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio if (*surfaces[i] == SF_GRID) { - cv = (srfGridMesh_t *) surfaces[i]; + cv = (srfBspSurface_t *) surfaces[i]; for ( m = 0 ; m < cv->height - 1 ; m++ ) { for ( n = 0 ; n < cv->width - 1 ; n++ ) { // We triangulate the grid and chop all triangles within @@ -407,10 +407,10 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio } else if (*surfaces[i] == SF_FACE) { - srfSurfaceFace_t *surf = ( srfSurfaceFace_t * ) surfaces[i]; + srfBspSurface_t *surf = ( srfBspSurface_t * ) surfaces[i]; // check the normal of this face - if (DotProduct(surf->plane.normal, projectionDir) > -0.5) { + if (DotProduct(surf->cullPlane.normal, projectionDir) > -0.5) { continue; } @@ -419,7 +419,7 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio for(j = 0; j < 3; j++) { v = surf->verts[tri->indexes[j]].xyz; - VectorMA(v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j]); + VectorMA(v, MARKER_OFFSET, surf->cullPlane.normal, clipPoints[0][j]); } // add the fragments of this face @@ -435,7 +435,7 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio } else if(*surfaces[i] == SF_TRIANGLES && r_marksOnTriangleMeshes->integer) { - srfTriangles_t *surf = (srfTriangles_t *) surfaces[i]; + srfBspSurface_t *surf = (srfBspSurface_t *) surfaces[i]; for(k = 0, tri = surf->triangles; k < surf->numTriangles; k++, tri++) { diff --git a/code/renderergl2/tr_model.c b/code/renderergl2/tr_model.c index 8feeab0e..6d9cd9e4 100644 --- a/code/renderergl2/tr_model.c +++ b/code/renderergl2/tr_model.c @@ -562,8 +562,6 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize, 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); diff --git a/code/renderergl2/tr_surface.c b/code/renderergl2/tr_surface.c index 9f83c7ba..5102e1d1 100644 --- a/code/renderergl2/tr_surface.c +++ b/code/renderergl2/tr_surface.c @@ -522,7 +522,7 @@ static qboolean RB_SurfaceVbo(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndex RB_SurfaceTriangles ============= */ -static void RB_SurfaceTriangles( srfTriangles_t *srf ) { +static void RB_SurfaceTriangles( srfBspSurface_t *srf ) { if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) ) { @@ -1247,7 +1247,7 @@ static void RB_SurfaceMesh(mdvSurface_t *surface) { RB_SurfaceFace ============== */ -static void RB_SurfaceFace( srfSurfaceFace_t *srf ) { +static void RB_SurfaceFace( srfBspSurface_t *srf ) { if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) ) { @@ -1296,7 +1296,7 @@ RB_SurfaceGrid Just copy the grid of points and triangulate ============= */ -static void RB_SurfaceGrid( srfGridMesh_t *srf ) { +static void RB_SurfaceGrid( srfBspSurface_t *srf ) { int i, j; float *xyz; float *texCoords, *lightCoords; @@ -1574,9 +1574,9 @@ static void RB_SurfaceFlare(srfFlare_t *surf) RB_AddFlare(surf, tess.fogNum, surf->origin, surf->color, surf->normal); } -static void RB_SurfaceVBOMesh(srfVBOMesh_t * srf) +static void RB_SurfaceVBOMesh(srfBspSurface_t * srf) { - RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, srf->firstIndex, + RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qfalse ); } diff --git a/code/renderergl2/tr_world.c b/code/renderergl2/tr_world.c index 0ee4ad28..dba15c45 100644 --- a/code/renderergl2/tr_world.c +++ b/code/renderergl2/tr_world.c @@ -208,16 +208,18 @@ static int R_DlightSurface( msurface_t *surf, int dlightBits ) { } } - if ( *surf->data == SF_FACE ) { - ((srfSurfaceFace_t *)surf->data)->dlightBits = dlightBits; - } else if ( *surf->data == SF_GRID ) { - ((srfGridMesh_t *)surf->data)->dlightBits = dlightBits; - } else if ( *surf->data == SF_TRIANGLES ) { - ((srfTriangles_t *)surf->data)->dlightBits = dlightBits; - } else if ( *surf->data == SF_VBO_MESH ) { - ((srfVBOMesh_t *)surf->data)->dlightBits = dlightBits; - } else { - dlightBits = 0; + switch(*surf->data) + { + case SF_FACE: + case SF_GRID: + case SF_TRIANGLES: + case SF_VBO_MESH: + ((srfBspSurface_t *)surf->data)->dlightBits = dlightBits; + break; + + default: + dlightBits = 0; + break; } if ( dlightBits ) { @@ -292,16 +294,18 @@ static int R_PshadowSurface( msurface_t *surf, int pshadowBits ) { } } - if ( *surf->data == SF_FACE ) { - ((srfSurfaceFace_t *)surf->data)->pshadowBits = pshadowBits; - } else if ( *surf->data == SF_GRID ) { - ((srfGridMesh_t *)surf->data)->pshadowBits = pshadowBits; - } else if ( *surf->data == SF_TRIANGLES ) { - ((srfTriangles_t *)surf->data)->pshadowBits = pshadowBits; - } else if ( *surf->data == SF_VBO_MESH ) { - ((srfVBOMesh_t *)surf->data)->pshadowBits = pshadowBits; - } else { - pshadowBits = 0; + switch(*surf->data) + { + case SF_FACE: + case SF_GRID: + case SF_TRIANGLES: + case SF_VBO_MESH: + ((srfBspSurface_t *)surf->data)->pshadowBits = pshadowBits; + break; + + default: + pshadowBits = 0; + break; } if ( pshadowBits ) { From e0a42885d95227af997635282c21c05e0889d5b7 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Mon, 28 Oct 2013 14:36:56 -0500 Subject: [PATCH 15/24] Clear more variables in CL_InitServerInfo Have cls.localServers use CL_InitServerInfo. Don't set cls.localServers netType to from.type, it's the wrong value. Note: server->visible is not cleared in CL_InitServerInfo, as stated by a comment below a place where CL_InitServerInfo is used. --- code/client/cl_main.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/code/client/cl_main.c b/code/client/cl_main.c index c03ba61e..5a30a681 100644 --- a/code/client/cl_main.c +++ b/code/client/cl_main.c @@ -2429,6 +2429,9 @@ void CL_InitServerInfo( serverInfo_t *server, netadr_t *address ) { server->game[0] = '\0'; server->gameType = 0; server->netType = 0; + server->punkbuster = 0; + server->g_humanplayers = 0; + server->g_needpass = 0; } #define MAX_SERVERSPERPACKET 256 @@ -3836,21 +3839,8 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) { // add this to the list cls.numlocalservers = i+1; - cls.localServers[i].adr = from; - cls.localServers[i].clients = 0; - cls.localServers[i].hostName[0] = '\0'; - cls.localServers[i].mapName[0] = '\0'; - cls.localServers[i].maxClients = 0; - cls.localServers[i].maxPing = 0; - cls.localServers[i].minPing = 0; - cls.localServers[i].ping = -1; - cls.localServers[i].game[0] = '\0'; - cls.localServers[i].gameType = 0; - cls.localServers[i].netType = from.type; - cls.localServers[i].punkbuster = 0; - cls.localServers[i].g_humanplayers = 0; - cls.localServers[i].g_needpass = 0; - + CL_InitServerInfo( &cls.localServers[i], &from ); + Q_strncpyz( info, MSG_ReadString( msg ), MAX_INFO_STRING ); if (strlen(info)) { if (info[strlen(info)-1] != '\n') { From 1515841b381a8058e3b24fe0987bef656328b87c Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Tue, 29 Oct 2013 20:46:12 -0500 Subject: [PATCH 16/24] Support IQMs with joints and no poses --- code/renderergl1/tr_local.h | 1 + code/renderergl1/tr_model_iqm.c | 57 ++++++++++++++++++++++++--------- code/renderergl2/tr_local.h | 1 + code/renderergl2/tr_model_iqm.c | 57 ++++++++++++++++++++++++--------- 4 files changed, 84 insertions(+), 32 deletions(-) diff --git a/code/renderergl1/tr_local.h b/code/renderergl1/tr_local.h index dd292bc6..71769e50 100644 --- a/code/renderergl1/tr_local.h +++ b/code/renderergl1/tr_local.h @@ -610,6 +610,7 @@ typedef struct { int num_frames; int num_surfaces; int num_joints; + int num_poses; struct srfIQModel_s *surfaces; float *positions; diff --git a/code/renderergl1/tr_model_iqm.c b/code/renderergl1/tr_model_iqm.c index a0cdbe75..c5a33739 100644 --- a/code/renderergl1/tr_model_iqm.c +++ b/code/renderergl1/tr_model_iqm.c @@ -25,6 +25,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define LL(x) x=LittleLong(x) +// 3x4 identity matrix +static float identityMatrix[12] = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0 +}; + static qboolean IQM_CheckRange( iqmHeader_t *header, int offset, int count,int size ) { // return true if the range specified by offset, count and size @@ -343,7 +350,9 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na } } - if( header->num_poses != header->num_joints ) { + if( header->num_poses != header->num_joints && header->num_poses != 0 ) { + ri.Printf(PRINT_WARNING, "R_LoadIQM: %s has %d poses and %d joints, must have the same number or 0 poses\n", + mod_name, header->num_poses, header->num_joints ); return qfalse; } @@ -379,7 +388,10 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na joint_names += strlen( (char *)header + header->ofs_text + joint->name ) + 1; } + } + if ( header->num_poses ) + { // check and swap poses if( IQM_CheckRange( header, header->ofs_poses, header->num_poses, sizeof(iqmPose_t) ) ) { @@ -438,7 +450,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na size = sizeof(iqmData_t); size += header->num_meshes * sizeof( srfIQModel_t ); size += header->num_joints * 12 * sizeof( float ); // joint mats - size += header->num_joints * header->num_frames * 12 * sizeof( float ); // pose mats + size += header->num_poses * header->num_frames * 12 * sizeof( float ); // pose mats if(header->ofs_bounds) size += header->num_frames * 6 * sizeof(float); // model bounds size += header->num_vertexes * 3 * sizeof(float); // positions @@ -462,16 +474,17 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na iqmData->num_frames = header->num_frames; iqmData->num_surfaces = header->num_meshes; iqmData->num_joints = header->num_joints; + iqmData->num_poses = header->num_poses; iqmData->surfaces = (srfIQModel_t *)(iqmData + 1); iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces); iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints; if(header->ofs_bounds) { - iqmData->bounds = iqmData->poseMats + 12 * header->num_joints * header->num_frames; + iqmData->bounds = iqmData->poseMats + 12 * header->num_poses * header->num_frames; iqmData->positions = iqmData->bounds + 6 * header->num_frames; } else - iqmData->positions = iqmData->poseMats + 12 * header->num_joints * header->num_frames; + iqmData->positions = iqmData->poseMats + 12 * header->num_poses * header->num_frames; iqmData->texcoords = iqmData->positions + 3 * header->num_vertexes; iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes; iqmData->tangents = iqmData->normals + 3 * header->num_vertexes; @@ -483,7 +496,10 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles); if ( header->num_joints == 0 ) - iqmData->jointMats = iqmData->poseMats = NULL; + iqmData->jointMats = NULL; + + if ( header->num_poses == 0 ) + iqmData->poseMats = NULL; // calculate joint matrices and their inverses // joint inverses are needed only until the pose matrices are calculated @@ -892,9 +908,21 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe, int *joint = data->jointParents; int i; - if ( oldframe == frame ) { - mat1 = data->poseMats + 12 * data->num_joints * frame; + if ( data->num_poses == 0 ) { for( i = 0; i < data->num_joints; i++, joint++ ) { + if( *joint >= 0 ) { + Matrix34Multiply( mat + 12 * *joint, + identityMatrix, mat + 12*i ); + } else { + Com_Memcpy( mat + 12*i, identityMatrix, 12 * sizeof(float) ); + } + } + return; + } + + if ( oldframe == frame ) { + mat1 = data->poseMats + 12 * data->num_poses * frame; + for( i = 0; i < data->num_poses; i++, joint++ ) { if( *joint >= 0 ) { Matrix34Multiply( mat + 12 * *joint, mat1 + 12*i, mat + 12*i ); @@ -903,10 +931,10 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe, } } } else { - mat1 = data->poseMats + 12 * data->num_joints * frame; - mat2 = data->poseMats + 12 * data->num_joints * oldframe; + mat1 = data->poseMats + 12 * data->num_poses * frame; + mat2 = data->poseMats + 12 * data->num_poses * oldframe; - for( i = 0; i < data->num_joints; i++, joint++ ) { + for( i = 0; i < data->num_poses; i++, joint++ ) { if( *joint >= 0 ) { float tmpMat[12]; InterpolateMatrix( mat1 + 12*i, mat2 + 12*i, @@ -974,7 +1002,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) { outColor = &tess.vertexColors[tess.numVertexes]; // compute interpolated joint matrices - if ( data->num_joints > 0 ) { + if ( data->num_poses > 0 ) { ComputePoseMats( data, frame, oldframe, backlerp, jointMats ); } @@ -986,12 +1014,9 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) { float nrmMat[9]; int vtx = i + surf->first_vertex; - if ( data->num_joints == 0 || data->blendWeights[4*vtx] <= 0 ) { + if ( data->num_poses == 0 || data->blendWeights[4*vtx] <= 0 ) { // no blend joint, use identity matrix. - for( j = 0; j < 3; j++ ) { - for( k = 0; k < 4; k++ ) - vtxMat[4*j+k] = ( k == j ) ? 1 : 0; - } + Com_Memcpy( vtxMat, identityMatrix, 12 * sizeof (float) ); } else { // compute the vertex matrix by blending the up to // four blend weights diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index 261f016c..f923d0dd 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -1086,6 +1086,7 @@ typedef struct { int num_frames; int num_surfaces; int num_joints; + int num_poses; struct srfIQModel_s *surfaces; float *positions; diff --git a/code/renderergl2/tr_model_iqm.c b/code/renderergl2/tr_model_iqm.c index 44c98ee0..89fe14af 100644 --- a/code/renderergl2/tr_model_iqm.c +++ b/code/renderergl2/tr_model_iqm.c @@ -25,6 +25,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define LL(x) x=LittleLong(x) +// 3x4 identity matrix +static float identityMatrix[12] = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0 +}; + static qboolean IQM_CheckRange( iqmHeader_t *header, int offset, int count,int size ) { // return true if the range specified by offset, count and size @@ -343,7 +350,9 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na } } - if( header->num_poses != header->num_joints ) { + if( header->num_poses != header->num_joints && header->num_poses != 0 ) { + ri.Printf(PRINT_WARNING, "R_LoadIQM: %s has %d poses and %d joints, must have the same number or 0 poses\n", + mod_name, header->num_poses, header->num_joints ); return qfalse; } @@ -379,7 +388,10 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na joint_names += strlen( (char *)header + header->ofs_text + joint->name ) + 1; } + } + if ( header->num_poses ) + { // check and swap poses if( IQM_CheckRange( header, header->ofs_poses, header->num_poses, sizeof(iqmPose_t) ) ) { @@ -438,7 +450,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na size = sizeof(iqmData_t); size += header->num_meshes * sizeof( srfIQModel_t ); size += header->num_joints * 12 * sizeof( float ); // joint mats - size += header->num_joints * header->num_frames * 12 * sizeof( float ); // pose mats + size += header->num_poses * header->num_frames * 12 * sizeof( float ); // pose mats if(header->ofs_bounds) size += header->num_frames * 6 * sizeof(float); // model bounds size += header->num_vertexes * 3 * sizeof(float); // positions @@ -462,16 +474,17 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na iqmData->num_frames = header->num_frames; iqmData->num_surfaces = header->num_meshes; iqmData->num_joints = header->num_joints; + iqmData->num_poses = header->num_poses; iqmData->surfaces = (srfIQModel_t *)(iqmData + 1); iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces); iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints; if(header->ofs_bounds) { - iqmData->bounds = iqmData->poseMats + 12 * header->num_joints * header->num_frames; + iqmData->bounds = iqmData->poseMats + 12 * header->num_poses * header->num_frames; iqmData->positions = iqmData->bounds + 6 * header->num_frames; } else - iqmData->positions = iqmData->poseMats + 12 * header->num_joints * header->num_frames; + iqmData->positions = iqmData->poseMats + 12 * header->num_poses * header->num_frames; iqmData->texcoords = iqmData->positions + 3 * header->num_vertexes; iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes; iqmData->tangents = iqmData->normals + 3 * header->num_vertexes; @@ -483,7 +496,10 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles); if ( header->num_joints == 0 ) - iqmData->jointMats = iqmData->poseMats = NULL; + iqmData->jointMats = NULL; + + if ( header->num_poses == 0 ) + iqmData->poseMats = NULL; // calculate joint matrices and their inverses // joint inverses are needed only until the pose matrices are calculated @@ -895,9 +911,21 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe, int *joint = data->jointParents; int i; - if ( oldframe == frame ) { - mat1 = data->poseMats + 12 * data->num_joints * frame; + if ( data->num_poses == 0 ) { for( i = 0; i < data->num_joints; i++, joint++ ) { + if( *joint >= 0 ) { + Matrix34Multiply( mat + 12 * *joint, + identityMatrix, mat + 12*i ); + } else { + Com_Memcpy( mat + 12*i, identityMatrix, 12 * sizeof(float) ); + } + } + return; + } + + if ( oldframe == frame ) { + mat1 = data->poseMats + 12 * data->num_poses * frame; + for( i = 0; i < data->num_poses; i++, joint++ ) { if( *joint >= 0 ) { Matrix34Multiply( mat + 12 * *joint, mat1 + 12*i, mat + 12*i ); @@ -906,10 +934,10 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe, } } } else { - mat1 = data->poseMats + 12 * data->num_joints * frame; - mat2 = data->poseMats + 12 * data->num_joints * oldframe; + mat1 = data->poseMats + 12 * data->num_poses * frame; + mat2 = data->poseMats + 12 * data->num_poses * oldframe; - for( i = 0; i < data->num_joints; i++, joint++ ) { + for( i = 0; i < data->num_poses; i++, joint++ ) { if( *joint >= 0 ) { float tmpMat[12]; InterpolateMatrix( mat1 + 12*i, mat2 + 12*i, @@ -977,7 +1005,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) { outColor = &tess.vertexColors[tess.numVertexes]; // compute interpolated joint matrices - if ( data->num_joints > 0 ) { + if ( data->num_poses > 0 ) { ComputePoseMats( data, frame, oldframe, backlerp, jointMats ); } @@ -989,12 +1017,9 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) { float nrmMat[9]; int vtx = i + surf->first_vertex; - if ( data->num_joints == 0 || data->blendWeights[4*vtx] <= 0 ) { + if ( data->num_poses == 0 || data->blendWeights[4*vtx] <= 0 ) { // no blend joint, use identity matrix. - for( j = 0; j < 3; j++ ) { - for( k = 0; k < 4; k++ ) - vtxMat[4*j+k] = ( k == j ) ? 1 : 0; - } + Com_Memcpy( vtxMat, identityMatrix, 12 * sizeof (float) ); } else { // compute the vertex matrix by blending the up to // four blend weights From 0bf1f3d0ba3a9c96dc5cfbb82981304cbec18b70 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Tue, 29 Oct 2013 22:09:06 -0500 Subject: [PATCH 17/24] Add support for IQM int blend indices and float blend weights Integer blend indices are converted to bytes at load, ioq3 doesn't allow more than 128 joints. Heavily based on code by @zippers. --- code/renderergl1/tr_local.h | 10 +++- code/renderergl1/tr_model_iqm.c | 88 ++++++++++++++++++++++++--------- code/renderergl2/tr_local.h | 10 +++- code/renderergl2/tr_model_iqm.c | 88 ++++++++++++++++++++++++--------- 4 files changed, 150 insertions(+), 46 deletions(-) diff --git a/code/renderergl1/tr_local.h b/code/renderergl1/tr_local.h index 71769e50..bce38dc9 100644 --- a/code/renderergl1/tr_local.h +++ b/code/renderergl1/tr_local.h @@ -618,10 +618,18 @@ typedef struct { float *normals; float *tangents; byte *blendIndexes; - byte *blendWeights; + union { + float *f; + byte *b; + } blendWeights; byte *colors; int *triangles; + // depending upon the exporter, blend indices and weights might be int/float + // as opposed to the recommended byte/byte, for example Noesis exports + // int/float whereas the official IQM tool exports byte/byte + byte blendWeightsType; // IQM_BYTE or IQM_FLOAT + int *jointParents; float *jointMats; float *poseMats; diff --git a/code/renderergl1/tr_model_iqm.c b/code/renderergl1/tr_model_iqm.c index c5a33739..19f9092d 100644 --- a/code/renderergl1/tr_model_iqm.c +++ b/code/renderergl1/tr_model_iqm.c @@ -150,6 +150,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na iqmData_t *iqmData; srfIQModel_t *surface; char meshName[MAX_QPATH]; + byte blendIndexesType, blendWeightsType; if( filesize < sizeof(iqmHeader_t) ) { return qfalse; @@ -271,11 +272,20 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na } break; case IQM_BLENDINDEXES: + if( (vertexarray->format != IQM_INT && + vertexarray->format != IQM_UBYTE) || + vertexarray->size != 4 ) { + return qfalse; + } + blendIndexesType = vertexarray->format; + break; case IQM_BLENDWEIGHTS: - if( vertexarray->format != IQM_UBYTE || + if( (vertexarray->format != IQM_FLOAT && + vertexarray->format != IQM_UBYTE) || vertexarray->size != 4 ) { return qfalse; } + blendWeightsType = vertexarray->format; break; case IQM_COLOR: if( vertexarray->format != IQM_UBYTE || @@ -458,12 +468,18 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na size += header->num_vertexes * 3 * sizeof(float); // normals size += header->num_vertexes * 4 * sizeof(float); // tangents size += header->num_vertexes * 4 * sizeof(byte); // blendIndexes - size += header->num_vertexes * 4 * sizeof(byte); // blendWeights size += header->num_vertexes * 4 * sizeof(byte); // colors size += header->num_joints * sizeof(int); // parents size += header->num_triangles * 3 * sizeof(int); // triangles size += joint_names; // joint names + // blendWeights + if (blendWeightsType == IQM_FLOAT) { + size += header->num_vertexes * 4 * sizeof(float); + } else { + size += header->num_vertexes * 4 * sizeof(byte); + } + mod->type = MOD_IQM; iqmData = (iqmData_t *)ri.Hunk_Alloc( size, h_low ); mod->modelData = iqmData; @@ -475,6 +491,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na iqmData->num_surfaces = header->num_meshes; iqmData->num_joints = header->num_joints; iqmData->num_poses = header->num_poses; + iqmData->blendWeightsType = blendWeightsType; iqmData->surfaces = (srfIQModel_t *)(iqmData + 1); iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces); iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints; @@ -489,8 +506,15 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes; iqmData->tangents = iqmData->normals + 3 * header->num_vertexes; iqmData->blendIndexes = (byte *)(iqmData->tangents + 4 * header->num_vertexes); - iqmData->blendWeights = iqmData->blendIndexes + 4 * header->num_vertexes; - iqmData->colors = iqmData->blendWeights + 4 * header->num_vertexes; + + if(blendWeightsType == IQM_FLOAT) { + iqmData->blendWeights.f = (float *)(iqmData->blendIndexes + 4 * header->num_vertexes); + iqmData->colors = (byte *)(iqmData->blendWeights.f + 4 * header->num_vertexes); + } else { + iqmData->blendWeights.b = iqmData->blendIndexes + 4 * header->num_vertexes; + iqmData->colors = iqmData->blendWeights.b + 4 * header->num_vertexes; + } + iqmData->jointParents = (int *)(iqmData->colors + 4 * header->num_vertexes); iqmData->triangles = iqmData->jointParents + header->num_joints; iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles); @@ -636,14 +660,28 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na n * sizeof(float) ); break; case IQM_BLENDINDEXES: - Com_Memcpy( iqmData->blendIndexes, - (byte *)header + vertexarray->offset, - n * sizeof(byte) ); + if( blendIndexesType == IQM_INT ) { + int *data = (int*)((byte*)header + vertexarray->offset); + for ( j = 0; j < n; j++ ) { + iqmData->blendIndexes[j] = (byte)LittleLong( data[j] ); + } + } else { + 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) ); + if( blendWeightsType == IQM_FLOAT ) { + float *data = (float*)((byte*)header + vertexarray->offset); + for ( j = 0; j < n; j++ ) { + iqmData->blendWeights.f[j] = LittleFloat( data[j] ); + } + } else { + Com_Memcpy( iqmData->blendWeights.b, + (byte *)header + vertexarray->offset, + n * sizeof(byte) ); + } break; case IQM_COLOR: Com_Memcpy( iqmData->colors, @@ -1013,25 +1051,31 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) { float vtxMat[12]; float nrmMat[9]; int vtx = i + surf->first_vertex; + float blendWeights[4]; + int numWeights; - if ( data->num_poses == 0 || data->blendWeights[4*vtx] <= 0 ) { + for ( numWeights = 0; numWeights < 4; numWeights++ ) { + if ( data->blendWeightsType == IQM_FLOAT ) + blendWeights[numWeights] = data->blendWeights.f[4*vtx + numWeights]; + else // IQM_BYTE + blendWeights[numWeights] = (float)data->blendWeights.b[4*vtx + numWeights] / 255.0f; + + if ( blendWeights[numWeights] <= 0 ) + break; + } + + if ( data->num_poses == 0 || numWeights == 0 ) { // no blend joint, use identity matrix. Com_Memcpy( vtxMat, identityMatrix, 12 * sizeof (float) ); } else { // compute the vertex matrix by blending the up to // four blend weights - for( k = 0; k < 12; k++ ) - vtxMat[k] = data->blendWeights[4*vtx] - * jointMats[12*data->blendIndexes[4*vtx] + k]; - for( j = 1; j < 4; j++ ) { - if( data->blendWeights[4*vtx + j] <= 0 ) - break; - for( k = 0; k < 12; k++ ) - vtxMat[k] += data->blendWeights[4*vtx + j] - * jointMats[12*data->blendIndexes[4*vtx + j] + k]; + Com_Memset( vtxMat, 0, 12 * sizeof (float) ); + for( j = 0; j < numWeights; j++ ) { + for( k = 0; k < 12; k++ ) { + vtxMat[k] += blendWeights[j] * jointMats[12*data->blendIndexes[4*vtx + j] + k]; + } } - for( k = 0; k < 12; k++ ) - vtxMat[k] *= 1.0f / 255.0f; } // compute the normal matrix as transpose of the adjoint diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index f923d0dd..b9975d39 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -1094,10 +1094,18 @@ typedef struct { float *normals; float *tangents; byte *blendIndexes; - byte *blendWeights; + union { + float *f; + byte *b; + } blendWeights; byte *colors; int *triangles; + // depending upon the exporter, blend indices and weights might be int/float + // as opposed to the recommended byte/byte, for example Noesis exports + // int/float whereas the official IQM tool exports byte/byte + byte blendWeightsType; // IQM_BYTE or IQM_FLOAT + int *jointParents; float *jointMats; float *poseMats; diff --git a/code/renderergl2/tr_model_iqm.c b/code/renderergl2/tr_model_iqm.c index 89fe14af..d40c78d5 100644 --- a/code/renderergl2/tr_model_iqm.c +++ b/code/renderergl2/tr_model_iqm.c @@ -150,6 +150,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na iqmData_t *iqmData; srfIQModel_t *surface; char meshName[MAX_QPATH]; + byte blendIndexesType, blendWeightsType; if( filesize < sizeof(iqmHeader_t) ) { return qfalse; @@ -271,11 +272,20 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na } break; case IQM_BLENDINDEXES: + if( (vertexarray->format != IQM_INT && + vertexarray->format != IQM_UBYTE) || + vertexarray->size != 4 ) { + return qfalse; + } + blendIndexesType = vertexarray->format; + break; case IQM_BLENDWEIGHTS: - if( vertexarray->format != IQM_UBYTE || + if( (vertexarray->format != IQM_FLOAT && + vertexarray->format != IQM_UBYTE) || vertexarray->size != 4 ) { return qfalse; } + blendWeightsType = vertexarray->format; break; case IQM_COLOR: if( vertexarray->format != IQM_UBYTE || @@ -458,12 +468,18 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na size += header->num_vertexes * 3 * sizeof(float); // normals size += header->num_vertexes * 4 * sizeof(float); // tangents size += header->num_vertexes * 4 * sizeof(byte); // blendIndexes - size += header->num_vertexes * 4 * sizeof(byte); // blendWeights size += header->num_vertexes * 4 * sizeof(byte); // colors size += header->num_joints * sizeof(int); // parents size += header->num_triangles * 3 * sizeof(int); // triangles size += joint_names; // joint names + // blendWeights + if (blendWeightsType == IQM_FLOAT) { + size += header->num_vertexes * 4 * sizeof(float); + } else { + size += header->num_vertexes * 4 * sizeof(byte); + } + mod->type = MOD_IQM; iqmData = (iqmData_t *)ri.Hunk_Alloc( size, h_low ); mod->modelData = iqmData; @@ -475,6 +491,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na iqmData->num_surfaces = header->num_meshes; iqmData->num_joints = header->num_joints; iqmData->num_poses = header->num_poses; + iqmData->blendWeightsType = blendWeightsType; iqmData->surfaces = (srfIQModel_t *)(iqmData + 1); iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces); iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints; @@ -489,8 +506,15 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes; iqmData->tangents = iqmData->normals + 3 * header->num_vertexes; iqmData->blendIndexes = (byte *)(iqmData->tangents + 4 * header->num_vertexes); - iqmData->blendWeights = iqmData->blendIndexes + 4 * header->num_vertexes; - iqmData->colors = iqmData->blendWeights + 4 * header->num_vertexes; + + if(blendWeightsType == IQM_FLOAT) { + iqmData->blendWeights.f = (float *)(iqmData->blendIndexes + 4 * header->num_vertexes); + iqmData->colors = (byte *)(iqmData->blendWeights.f + 4 * header->num_vertexes); + } else { + iqmData->blendWeights.b = iqmData->blendIndexes + 4 * header->num_vertexes; + iqmData->colors = iqmData->blendWeights.b + 4 * header->num_vertexes; + } + iqmData->jointParents = (int *)(iqmData->colors + 4 * header->num_vertexes); iqmData->triangles = iqmData->jointParents + header->num_joints; iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles); @@ -636,14 +660,28 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na n * sizeof(float) ); break; case IQM_BLENDINDEXES: - Com_Memcpy( iqmData->blendIndexes, - (byte *)header + vertexarray->offset, - n * sizeof(byte) ); + if( blendIndexesType == IQM_INT ) { + int *data = (int*)((byte*)header + vertexarray->offset); + for ( j = 0; j < n; j++ ) { + iqmData->blendIndexes[j] = (byte)LittleLong( data[j] ); + } + } else { + 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) ); + if( blendWeightsType == IQM_FLOAT ) { + float *data = (float*)((byte*)header + vertexarray->offset); + for ( j = 0; j < n; j++ ) { + iqmData->blendWeights.f[j] = LittleFloat( data[j] ); + } + } else { + Com_Memcpy( iqmData->blendWeights.b, + (byte *)header + vertexarray->offset, + n * sizeof(byte) ); + } break; case IQM_COLOR: Com_Memcpy( iqmData->colors, @@ -1016,25 +1054,31 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) { float vtxMat[12]; float nrmMat[9]; int vtx = i + surf->first_vertex; + float blendWeights[4]; + int numWeights; - if ( data->num_poses == 0 || data->blendWeights[4*vtx] <= 0 ) { + for ( numWeights = 0; numWeights < 4; numWeights++ ) { + if ( data->blendWeightsType == IQM_FLOAT ) + blendWeights[numWeights] = data->blendWeights.f[4*vtx + numWeights]; + else // IQM_BYTE + blendWeights[numWeights] = (float)data->blendWeights.b[4*vtx + numWeights] / 255.0f; + + if ( blendWeights[numWeights] <= 0 ) + break; + } + + if ( data->num_poses == 0 || numWeights == 0 ) { // no blend joint, use identity matrix. Com_Memcpy( vtxMat, identityMatrix, 12 * sizeof (float) ); } else { // compute the vertex matrix by blending the up to // four blend weights - for( k = 0; k < 12; k++ ) - vtxMat[k] = data->blendWeights[4*vtx] - * jointMats[12*data->blendIndexes[4*vtx] + k]; - for( j = 1; j < 4; j++ ) { - if( data->blendWeights[4*vtx + j] <= 0 ) - break; - for( k = 0; k < 12; k++ ) - vtxMat[k] += data->blendWeights[4*vtx + j] - * jointMats[12*data->blendIndexes[4*vtx + j] + k]; + Com_Memset( vtxMat, 0, 12 * sizeof (float) ); + for( j = 0; j < numWeights; j++ ) { + for( k = 0; k < 12; k++ ) { + vtxMat[k] += blendWeights[j] * jointMats[12*data->blendIndexes[4*vtx + j] + k]; + } } - for( k = 0; k < 12; k++ ) - vtxMat[k] *= 1.0f / 255.0f; } // compute the normal matrix as transpose of the adjoint From c28fabf505a638955f66e23cf9dfdeb8f5cea4e5 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Tue, 29 Oct 2013 23:07:15 -0500 Subject: [PATCH 18/24] IQM int/float vertex arrays were already swapped --- code/renderergl1/tr_model_iqm.c | 9 ++++----- code/renderergl2/tr_model_iqm.c | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/code/renderergl1/tr_model_iqm.c b/code/renderergl1/tr_model_iqm.c index 19f9092d..ec885742 100644 --- a/code/renderergl1/tr_model_iqm.c +++ b/code/renderergl1/tr_model_iqm.c @@ -663,7 +663,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na if( blendIndexesType == IQM_INT ) { int *data = (int*)((byte*)header + vertexarray->offset); for ( j = 0; j < n; j++ ) { - iqmData->blendIndexes[j] = (byte)LittleLong( data[j] ); + iqmData->blendIndexes[j] = (byte)data[j]; } } else { Com_Memcpy( iqmData->blendIndexes, @@ -673,10 +673,9 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na break; case IQM_BLENDWEIGHTS: if( blendWeightsType == IQM_FLOAT ) { - float *data = (float*)((byte*)header + vertexarray->offset); - for ( j = 0; j < n; j++ ) { - iqmData->blendWeights.f[j] = LittleFloat( data[j] ); - } + Com_Memcpy( iqmData->blendWeights.f, + (byte *)header + vertexarray->offset, + n * sizeof(float) ); } else { Com_Memcpy( iqmData->blendWeights.b, (byte *)header + vertexarray->offset, diff --git a/code/renderergl2/tr_model_iqm.c b/code/renderergl2/tr_model_iqm.c index d40c78d5..64ed3407 100644 --- a/code/renderergl2/tr_model_iqm.c +++ b/code/renderergl2/tr_model_iqm.c @@ -663,7 +663,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na if( blendIndexesType == IQM_INT ) { int *data = (int*)((byte*)header + vertexarray->offset); for ( j = 0; j < n; j++ ) { - iqmData->blendIndexes[j] = (byte)LittleLong( data[j] ); + iqmData->blendIndexes[j] = (byte)data[j]; } } else { Com_Memcpy( iqmData->blendIndexes, @@ -673,10 +673,9 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na break; case IQM_BLENDWEIGHTS: if( blendWeightsType == IQM_FLOAT ) { - float *data = (float*)((byte*)header + vertexarray->offset); - for ( j = 0; j < n; j++ ) { - iqmData->blendWeights.f[j] = LittleFloat( data[j] ); - } + Com_Memcpy( iqmData->blendWeights.f, + (byte *)header + vertexarray->offset, + n * sizeof(float) ); } else { Com_Memcpy( iqmData->blendWeights.b, (byte *)header + vertexarray->offset, From f55bb272b6b0d863b57c7e9277838c0c2d5ee069 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Tue, 29 Oct 2013 23:11:32 -0500 Subject: [PATCH 19/24] Fix IQM comments refering to IQM_BYTE instead of IQM_UBYTE --- code/renderergl1/tr_local.h | 2 +- code/renderergl1/tr_model_iqm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/renderergl1/tr_local.h b/code/renderergl1/tr_local.h index bce38dc9..b5550c3d 100644 --- a/code/renderergl1/tr_local.h +++ b/code/renderergl1/tr_local.h @@ -628,7 +628,7 @@ typedef struct { // depending upon the exporter, blend indices and weights might be int/float // as opposed to the recommended byte/byte, for example Noesis exports // int/float whereas the official IQM tool exports byte/byte - byte blendWeightsType; // IQM_BYTE or IQM_FLOAT + byte blendWeightsType; // IQM_UBYTE or IQM_FLOAT int *jointParents; float *jointMats; diff --git a/code/renderergl1/tr_model_iqm.c b/code/renderergl1/tr_model_iqm.c index ec885742..8c05f294 100644 --- a/code/renderergl1/tr_model_iqm.c +++ b/code/renderergl1/tr_model_iqm.c @@ -1056,7 +1056,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) { for ( numWeights = 0; numWeights < 4; numWeights++ ) { if ( data->blendWeightsType == IQM_FLOAT ) blendWeights[numWeights] = data->blendWeights.f[4*vtx + numWeights]; - else // IQM_BYTE + else blendWeights[numWeights] = (float)data->blendWeights.b[4*vtx + numWeights] / 255.0f; if ( blendWeights[numWeights] <= 0 ) From 611d9134436bd6ee9ad858c5c2bb7c20f615f71a Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Tue, 29 Oct 2013 23:18:05 -0500 Subject: [PATCH 20/24] Initialize blendIndexesType and blendWeightsType --- code/renderergl1/tr_model_iqm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/renderergl1/tr_model_iqm.c b/code/renderergl1/tr_model_iqm.c index 8c05f294..0f99f160 100644 --- a/code/renderergl1/tr_model_iqm.c +++ b/code/renderergl1/tr_model_iqm.c @@ -206,6 +206,8 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na return qfalse; } + blendIndexesType = blendWeightsType = IQM_UBYTE; + // check and swap vertex arrays if( IQM_CheckRange( header, header->ofs_vertexarrays, header->num_vertexarrays, From 0f30dad10a55c5f962ddbc7f3162fef751c3273a Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Tue, 29 Oct 2013 23:22:02 -0500 Subject: [PATCH 21/24] Merge last two commits into renderergl2 --- code/renderergl2/tr_local.h | 2 +- code/renderergl2/tr_model_iqm.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index b9975d39..06f17ffa 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -1104,7 +1104,7 @@ typedef struct { // depending upon the exporter, blend indices and weights might be int/float // as opposed to the recommended byte/byte, for example Noesis exports // int/float whereas the official IQM tool exports byte/byte - byte blendWeightsType; // IQM_BYTE or IQM_FLOAT + byte blendWeightsType; // IQM_UBYTE or IQM_FLOAT int *jointParents; float *jointMats; diff --git a/code/renderergl2/tr_model_iqm.c b/code/renderergl2/tr_model_iqm.c index 64ed3407..44c4a956 100644 --- a/code/renderergl2/tr_model_iqm.c +++ b/code/renderergl2/tr_model_iqm.c @@ -206,6 +206,8 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na return qfalse; } + blendIndexesType = blendWeightsType = IQM_UBYTE; + // check and swap vertex arrays if( IQM_CheckRange( header, header->ofs_vertexarrays, header->num_vertexarrays, @@ -1059,7 +1061,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) { for ( numWeights = 0; numWeights < 4; numWeights++ ) { if ( data->blendWeightsType == IQM_FLOAT ) blendWeights[numWeights] = data->blendWeights.f[4*vtx + numWeights]; - else // IQM_BYTE + else blendWeights[numWeights] = (float)data->blendWeights.b[4*vtx + numWeights] / 255.0f; if ( blendWeights[numWeights] <= 0 ) From 6bd52de44ed97da653ea5bce7aa2316966b2fb58 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sat, 2 Nov 2013 02:35:59 -0500 Subject: [PATCH 22/24] Remove unused shader state code from tr_local.h --- code/renderergl1/tr_local.h | 20 -------------------- code/renderergl2/tr_local.h | 20 -------------------- 2 files changed, 40 deletions(-) diff --git a/code/renderergl1/tr_local.h b/code/renderergl1/tr_local.h index b5550c3d..6e8b595b 100644 --- a/code/renderergl1/tr_local.h +++ b/code/renderergl1/tr_local.h @@ -41,10 +41,6 @@ typedef unsigned int glIndex_t; #define SHADERNUM_BITS 14 #define MAX_SHADERS (1< Date: Sat, 2 Nov 2013 02:59:31 -0500 Subject: [PATCH 23/24] Remove vertexLightmap from textureBundle_t, it's never qtrue --- code/renderergl1/tr_local.h | 1 - code/renderergl1/tr_shade.c | 9 ++------- code/renderergl2/tr_local.h | 1 - code/renderergl2/tr_shade.c | 9 ++------- 4 files changed, 4 insertions(+), 16 deletions(-) diff --git a/code/renderergl1/tr_local.h b/code/renderergl1/tr_local.h index 6e8b595b..6f54b956 100644 --- a/code/renderergl1/tr_local.h +++ b/code/renderergl1/tr_local.h @@ -262,7 +262,6 @@ typedef struct { int videoMapHandle; qboolean isLightmap; - qboolean vertexLightmap; qboolean isVideoMap; } textureBundle_t; diff --git a/code/renderergl1/tr_shade.c b/code/renderergl1/tr_shade.c index 04cef08b..08648b2e 100644 --- a/code/renderergl1/tr_shade.c +++ b/code/renderergl1/tr_shade.c @@ -1145,12 +1145,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) // // set state // - if ( pStage->bundle[0].vertexLightmap && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer ) - { - GL_Bind( tr.whiteImage ); - } - else - R_BindAnimatedImage( &pStage->bundle[0] ); + R_BindAnimatedImage( &pStage->bundle[0] ); GL_State( pStage->stateBits ); @@ -1160,7 +1155,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) R_DrawElements( input->numIndexes, input->indexes ); } // allow skipping out to show just lightmaps during development - if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) ) + if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) ) { break; } diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index ec676c2d..0cc1f491 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -350,7 +350,6 @@ typedef struct { int videoMapHandle; qboolean isLightmap; - qboolean vertexLightmap; qboolean isVideoMap; } textureBundle_t; diff --git a/code/renderergl2/tr_shade.c b/code/renderergl2/tr_shade.c index 6ccbacf1..74b8fe1f 100644 --- a/code/renderergl2/tr_shade.c +++ b/code/renderergl2/tr_shade.c @@ -1325,12 +1325,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) // // set state // - if ( pStage->bundle[0].vertexLightmap && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer ) - { - GL_BindToTMU( tr.whiteImage, 0 ); - } - else - R_BindAnimatedImageToTMU( &pStage->bundle[0], 0 ); + R_BindAnimatedImageToTMU( &pStage->bundle[0], 0 ); GLSL_SetUniformInt(sp, UNIFORM_TEXTURE1ENV, 0); } @@ -1354,7 +1349,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) } // allow skipping out to show just lightmaps during development - if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) ) + if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) ) { break; } From 7ae49cc2373174256fcc103fd41801e235ac7b9f Mon Sep 17 00:00:00 2001 From: Tim Angus Date: Sat, 2 Nov 2013 19:11:14 +0000 Subject: [PATCH 24/24] Fix video recording sync drift (patch refactored but original author unknown) --- code/client/cl_main.c | 10 +++++----- code/client/client.h | 3 +++ code/client/snd_dma.c | 8 +++++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/code/client/cl_main.c b/code/client/cl_main.c index 5a30a681..143e1201 100644 --- a/code/client/cl_main.c +++ b/code/client/cl_main.c @@ -2940,13 +2940,13 @@ void CL_Frame ( int msec ) { if ( CL_VideoRecording( ) && cl_aviFrameRate->integer && msec) { // save the current screen if ( clc.state == CA_ACTIVE || cl_forceavidemo->integer) { + float fps = MIN(cl_aviFrameRate->value * com_timescale->value, 1000.0f); + float frameDuration = MAX(1000.0f / fps, 1.0f) + clc.aviVideoFrameRemainder; + CL_TakeVideoFrame( ); - // fixed time for next frame' - msec = (int)ceil( (1000.0f / cl_aviFrameRate->value) * com_timescale->value ); - if (msec == 0) { - msec = 1; - } + msec = (int)frameDuration; + clc.aviVideoFrameRemainder = frameDuration - msec; } } diff --git a/code/client/client.h b/code/client/client.h index a6155555..a9b3e51e 100644 --- a/code/client/client.h +++ b/code/client/client.h @@ -233,6 +233,9 @@ typedef struct { int timeDemoMaxDuration; // maximum frame duration unsigned char timeDemoDurations[ MAX_TIMEDEMO_DURATIONS ]; // log of frame durations + float aviVideoFrameRemainder; + float aviSoundFrameRemainder; + #ifdef USE_VOIP qboolean voipEnabled; qboolean speexInitialized; diff --git a/code/client/snd_dma.c b/code/client/snd_dma.c index 869c6197..1e78f350 100644 --- a/code/client/snd_dma.c +++ b/code/client/snd_dma.c @@ -1242,7 +1242,13 @@ void S_GetSoundtime(void) if( CL_VideoRecording( ) ) { - s_soundtime += (int)ceil( dma.speed / cl_aviFrameRate->value ); + float fps = MIN(cl_aviFrameRate->value, 1000.0f); + float frameDuration = MAX(dma.speed / fps, 1.0f) + clc.aviSoundFrameRemainder; + + int msec = (int)frameDuration; + s_soundtime += msec; + clc.aviSoundFrameRemainder = frameDuration - msec; + return; }