fix offset/reliefmapping by using the proper miplevel - NOTE: this makes use of a...
authordivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 12 Mar 2011 20:46:27 +0000 (20:46 +0000)
committerdivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 12 Mar 2011 20:46:27 +0000 (20:46 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@10913 d7cf8633-e32d-0410-b094-e92efae38249

gl_backend.c
gl_rmain.c
glquake.h
shader_glsl.h
shader_hlsl.h
vid_sdl.c
vid_shared.c

index 26fe7c2..68067af 100644 (file)
@@ -2419,6 +2419,8 @@ unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **ver
        qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
        qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
        qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
+       if(qglBindFragDataLocation)
+               qglBindFragDataLocation(programobject, 0, "dp_FragColor");
 
        if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
                goto cleanup;
index 9d43f08..790dbca 100644 (file)
@@ -982,6 +982,15 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode
 
        // the first pretext is which type of shader to compile as
        // (later these will all be bound together as a program object)
+       if(qglBindFragDataLocation && (permutation & SHADERPERMUTATION_OFFSETMAPPING)) // we use textureGrad() which is glsl 1.30
+       {
+               vertstrings_list[vertstrings_count++] = "#version 130\n";
+               geomstrings_list[geomstrings_count++] = "#version 130\n";
+               fragstrings_list[fragstrings_count++] = "#version 130\n";
+       }
+
+       // the first pretext is which type of shader to compile as
+       // (later these will all be bound together as a program object)
        vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
        geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
        fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
index 90ef1a7..04c71f1 100644 (file)
--- a/glquake.h
+++ b/glquake.h
@@ -847,6 +847,7 @@ extern void (GLAPIENTRY *qglVertexAttribPointer)(GLuint index, GLint size, GLenu
 extern void (GLAPIENTRY *qglEnableVertexAttribArray)(GLuint index);
 extern void (GLAPIENTRY *qglDisableVertexAttribArray)(GLuint index);
 extern void (GLAPIENTRY *qglBindAttribLocation)(GLuint programObj, GLuint index, const GLchar *name);
+extern void (GLAPIENTRY *qglBindFragDataLocation)(GLuint programObj, GLuint index, const GLchar *name);
 extern void (GLAPIENTRY *qglGetActiveAttrib)(GLuint programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
 extern GLint (GLAPIENTRY *qglGetAttribLocation)(GLuint programObj, const GLchar *name);
 extern void (GLAPIENTRY *qglGetVertexAttribdv)(GLuint index, GLenum pname, GLdouble *params);
index 5cfeef0..a6fef69 100644 (file)
@@ -9,6 +9,23 @@
 "#define highp\n"
 "#endif\n"
 "\n"
+"#if __VERSION__ >= 130\n"
+"# ifdef VERTEX_SHADER\n"
+"#  define varying out\n"
+"#  define attribute in\n"
+"# endif\n"
+"# ifdef FRAGMENT_SHADER\n"
+"out vec4 dp_FragColor;\n"
+"#  define gl_FragColor dp_FragColor\n"
+"#  define varying in\n"
+"#  define attribute in\n"
+"# endif\n"
+"# define texture1D texture\n"
+"# define texture2D texture\n"
+"# define texture3D texture\n"
+"# define textureCube texture\n"
+"#endif\n"
+"\n"
 "#ifdef VERTEX_SHADER\n"
 "attribute vec4 Attrib_Position;  // vertex\n"
 "attribute vec4 Attrib_Color;     // color\n"
 "\n"
 "#ifdef USEOFFSETMAPPING\n"
 "uniform mediump float OffsetMapping_Scale;\n"
-"vec2 OffsetMapping(vec2 TexCoord)\n"
+"vec2 OffsetMapping(vec2 TexCoord, vec2 dPdx, vec2 dPdy)\n"
 "{\n"
 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
 "      // 14 sample relief mapping: linear search and then binary search\n"
 "      vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
 "      vec3 RT = vec3(TexCoord, 1);\n"
 "      OffsetVector *= 0.1;\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
-"      RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
-"      RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
-"      RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
-"      RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
+"      RT += OffsetVector *  step(textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector * (step(textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z)          - 0.5);\n"
+"      RT += OffsetVector * (step(textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z) * 0.5    - 0.25);\n"
+"      RT += OffsetVector * (step(textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z) * 0.25   - 0.125);\n"
+"      RT += OffsetVector * (step(textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z) * 0.125  - 0.0625);\n"
+"      RT += OffsetVector * (step(textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z) * 0.0625 - 0.03125);\n"
 "      return RT.xy;\n"
 "#else\n"
 "      // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
 "      //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
 "      vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
 "      OffsetVector *= 0.5;\n"
-"      TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
-"      TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
+"      TexCoord += OffsetVector * (1.0 - textureGrad(Texture_Normal, TexCoord, dPdx, dPdy).a);\n"
+"      TexCoord += OffsetVector * (1.0 - textureGrad(Texture_Normal, TexCoord, dPdx, dPdy).a);\n"
 "      return TexCoord;\n"
 "#endif\n"
 "}\n"
 "{\n"
 "#ifdef USEOFFSETMAPPING\n"
 "      // apply offsetmapping\n"
-"      vec2 TexCoord = OffsetMapping(TexCoordSurfaceLightmap.xy);\n"
+"      vec2 dPdx = dFdx(TexCoordSurfaceLightmap.xy);\n"
+"      vec2 dPdy = dFdy(TexCoordSurfaceLightmap.xy);\n"
+"      vec2 TexCoordOffset = OffsetMapping(TexCoordSurfaceLightmap.xy, dPdx, dPdy);\n"
+"# define offsetMappedTexture2D(t) textureGrad(t, TexCoordOffset, dPdx, dPdy)\n"
 "#else\n"
-"# define TexCoord (TexCoordSurfaceLightmap.xy)\n"
+"# define offsetMappedTexture2D(t) texture2D(t, TexCoordSurfaceLightmap.xy)\n"
 "#endif\n"
 "\n"
 "#ifdef USEALPHAKILL\n"
-"      if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
+"      if (offsetMappedTexture2D(Texture_Color).a < 0.5)\n"
 "              discard;\n"
 "#endif\n"
 "\n"
 "#ifdef USEVERTEXTEXTUREBLEND\n"
-"      float alpha = texture2D(Texture_Color, TexCoord).a;\n"
+"      float alpha = offsetMappedTexture2D(Texture_Color).a;\n"
 "      float terrainblend = clamp(float(VertexColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
 "      //float terrainblend = min(float(VertexColor.a) * alpha * 2.0, float(1.0));\n"
 "      //float terrainblend = float(VertexColor.a) * alpha > 0.5;\n"
 "#endif\n"
 "\n"
 "#ifdef USEVERTEXTEXTUREBLEND\n"
-"      vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
-"      float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
+"      vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(offsetMappedTexture2D(Texture_Normal)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
+"      float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, offsetMappedTexture2D(Texture_Gloss).a, terrainblend);\n"
 "#else\n"
-"      vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
-"      float a = texture2D(Texture_Gloss, TexCoord).a;\n"
+"      vec3 surfacenormal = vec3(offsetMappedTexture2D(Texture_Normal)) - vec3(0.5, 0.5, 0.5);\n"
+"      float a = offsetMappedTexture2D(Texture_Gloss).a;\n"
 "#endif\n"
 "\n"
 "      gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
 "{\n"
 "#ifdef USEOFFSETMAPPING\n"
 "      // apply offsetmapping\n"
-"      vec2 TexCoord = OffsetMapping(TexCoordSurfaceLightmap.xy);\n"
+"      vec2 dPdx = dFdx(TexCoordSurfaceLightmap.xy);\n"
+"      vec2 dPdy = dFdy(TexCoordSurfaceLightmap.xy);\n"
+"      vec2 TexCoordOffset = OffsetMapping(TexCoordSurfaceLightmap.xy, dPdx, dPdy);\n"
+"# define offsetMappedTexture2D(t) textureGrad(t, TexCoordOffset, dPdx, dPdy)\n"
 "#else\n"
-"# define TexCoord (TexCoordSurfaceLightmap.xy)\n"
+"# define offsetMappedTexture2D(t) texture2D(t, TexCoordSurfaceLightmap.xy)\n"
 "#endif\n"
 "\n"
 "      // combine the diffuse textures (base, pants, shirt)\n"
-"      myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
+"      myhalf4 color = myhalf4(offsetMappedTexture2D(Texture_Color));\n"
 "#ifdef USEALPHAKILL\n"
 "      if (color.a < 0.5)\n"
 "              discard;\n"
 "#endif\n"
 "      color.a *= Alpha;\n"
 "#ifdef USECOLORMAPPING\n"
-"      color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
+"      color.rgb += myhalf3(offsetMappedTexture2D(Texture_Pants)) * Color_Pants + myhalf3(offsetMappedTexture2D(Texture_Shirt)) * Color_Shirt;\n"
 "#endif\n"
 "#ifdef USEVERTEXTEXTUREBLEND\n"
 "      myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
 "\n"
 "      // get the surface normal\n"
 "#ifdef USEVERTEXTEXTUREBLEND\n"
-"      myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
+"      myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(offsetMappedTexture2D(Texture_Normal)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
 "#else\n"
-"      myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
+"      myhalf3 surfacenormal = normalize(myhalf3(offsetMappedTexture2D(Texture_Normal)) - myhalf3(0.5, 0.5, 0.5));\n"
 "#endif\n"
 "\n"
 "      // get the material colors\n"
 "      myhalf3 diffusetex = color.rgb;\n"
 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
 "# ifdef USEVERTEXTEXTUREBLEND\n"
-"      myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
+"      myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(offsetMappedTexture2D(Texture_Gloss)), terrainblend);\n"
 "# else\n"
-"      myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
+"      myhalf4 glosstex = myhalf4(offsetMappedTexture2D(Texture_Gloss));\n"
 "# endif\n"
 "#endif\n"
 "\n"
 "      vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
 "      vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
 "      vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
-"      diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
+"      diffusetex += myhalf3(offsetMappedTexture2D(Texture_ReflectMask)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
 "#endif\n"
 "\n"
 "\n"
 "\n"
 "#ifdef USEGLOW\n"
 "#ifdef USEVERTEXTEXTUREBLEND\n"
-"      color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
+"      color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(offsetMappedTexture2D(Texture_Glow)), terrainblend) * Color_Glow;\n"
 "#else\n"
-"      color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
+"      color.rgb += myhalf3(offsetMappedTexture2D(Texture_Glow)) * Color_Glow;\n"
 "#endif\n"
 "#endif\n"
 "\n"
 "      // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
 "#ifdef USEREFLECTION\n"
 "      vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
-"      //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
+"      //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(offsetMappedTexture2D(Texture_Normal)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
 "      vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
-"      vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
+"      vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(offsetMappedTexture2D(Texture_Normal)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
 "      // FIXME temporary hack to detect the case that the reflection\n"
 "      // gets blackened at edges due to leaving the area that contains actual\n"
 "      // content.\n"
index 19bf6b8..41aa34e 100644 (file)
 "#endif\n"
 "\n"
 "#ifdef USEOFFSETMAPPING\n"
-"float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
+"float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal, float2 dPdx, float2 dPdy)\n"
 "{\n"
 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
 "      // 14 sample relief mapping: linear search and then binary search\n"
 "      float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
 "      float3 RT = float3(TexCoord, 1);\n"
 "      OffsetVector *= 0.1;\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
-"      RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
-"      RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
-"      RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
-"      RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
+"      RT += OffsetVector *  step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector *  step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
+"      RT += OffsetVector * (step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z)          - 0.5);\n"
+"      RT += OffsetVector * (step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z) * 0.5    - 0.25);\n"
+"      RT += OffsetVector * (step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z) * 0.25   - 0.125);\n"
+"      RT += OffsetVector * (step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z) * 0.125  - 0.0625);\n"
+"      RT += OffsetVector * (step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z) * 0.0625 - 0.03125);\n"
 "      return RT.xy;\n"
 "#else\n"
 "      // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
 "      //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
 "      float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
 "      OffsetVector *= 0.5;\n"
-"      TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
-"      TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
+"      TexCoord += OffsetVector * (1.0 - tex2Dgrad(Texture_Normal, TexCoord, dPdx, dPdy).a);\n"
+"      TexCoord += OffsetVector * (1.0 - tex2Dgrad(Texture_Normal, TexCoord, dPdx, dPdy).a);\n"
 "      return TexCoord;\n"
 "#endif\n"
 "}\n"
 "      float2 TexCoord = TexCoordBoth.xy;\n"
 "#ifdef USEOFFSETMAPPING\n"
 "      // apply offsetmapping\n"
-"      float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
-"#define TexCoord TexCoordOffset\n"
+"      float2 dPdx = ddx(TexCoord);\n"
+"      float2 dPdy = ddy(TexCoord);\n"
+"      float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal, dPdx, dPdy);\n"
+"# define offsetMappedTexture2D(t) tex2Dgrad(t, TexCoordOffset, dPdx, dPdy)\n"
+"#else\n"
+"# define offsetMappedTexture2D(t) tex2D(t, TexCoord)\n"
 "#endif\n"
 "\n"
 "#ifdef USEALPHAKILL\n"
-"      if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
+"      if (offsetMappedTexture2D(Texture_Color).a < 0.5)\n"
 "              discard;\n"
 "#endif\n"
 "\n"
 "#ifdef USEVERTEXTEXTUREBLEND\n"
-"      float alpha = tex2D(Texture_Color, TexCoord).a;\n"
+"      float alpha = offsetMappedTexture2D(Texture_Color).a;\n"
 "      float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
 "      //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
 "      //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
 "#endif\n"
 "\n"
 "#ifdef USEVERTEXTEXTUREBLEND\n"
-"      float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
-"      float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
+"      float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, offsetMappedTexture2D(Texture_Normal).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
+"      float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, offsetMappedTexture2D(Texture_Gloss).a, terrainblend);\n"
 "#else\n"
-"      float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
-"      float a = tex2D(Texture_Gloss, TexCoord).a;\n"
+"      float3 surfacenormal = offsetMappedTexture2D(Texture_Normal).rgb - float3(0.5, 0.5, 0.5);\n"
+"      float a = offsetMappedTexture2D(Texture_Gloss).a;\n"
 "#endif\n"
 "\n"
 "#ifdef HLSL\n"
 "#endif\n"
 "#ifdef USEOFFSETMAPPING\n"
 "      // apply offsetmapping\n"
-"      float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
-"#define TexCoord TexCoordOffset\n"
+"      float2 dPdx = ddx(TexCoord);\n"
+"      float2 dPdy = ddy(TexCoord);\n"
+"      float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal, dPdx, dPdy);\n"
+"# define offsetMappedTexture2D(t) tex2Dgrad(t, TexCoordOffset, dPdx, dPdy)\n"
+"#else\n"
+"# define offsetMappedTexture2D(t) tex2D(t, TexCoord)\n"
 "#endif\n"
 "\n"
 "      // combine the diffuse textures (base, pants, shirt)\n"
-"      half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
+"      half4 color = half4(offsetMappedTexture2D(Texture_Color));\n"
 "#ifdef USEALPHAKILL\n"
 "      if (color.a < 0.5)\n"
 "              discard;\n"
 "#endif\n"
 "      color.a *= Alpha;\n"
 "#ifdef USECOLORMAPPING\n"
-"      color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
+"      color.rgb += half3(offsetMappedTexture2D(Texture_Pants).rgb) * Color_Pants + half3(offsetMappedTexture2D(Texture_Shirt).rgb) * Color_Shirt;\n"
 "#endif\n"
 "#ifdef USEVERTEXTEXTUREBLEND\n"
 "      half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
 "\n"
 "      // get the surface normal\n"
 "#ifdef USEVERTEXTEXTUREBLEND\n"
-"      half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
+"      half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, offsetMappedTexture2D(Texture_Normal).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
 "#else\n"
-"      half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
+"      half3 surfacenormal = half3(normalize(half3(offsetMappedTexture2D(Texture_Normal).rgb) - half3(0.5, 0.5, 0.5)));\n"
 "#endif\n"
 "\n"
 "      // get the material colors\n"
 "      half3 diffusetex = color.rgb;\n"
 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
 "# ifdef USEVERTEXTEXTUREBLEND\n"
-"      half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
+"      half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), offsetMappedTexture2D(Texture_Gloss), terrainblend));\n"
 "# else\n"
-"      half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
+"      half4 glosstex = half4(offsetMappedTexture2D(Texture_Gloss));\n"
 "# endif\n"
 "#endif\n"
 "\n"
 "      float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
 "      float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
 "      float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
-"      diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
+"      diffusetex += half3(offsetMappedTexture2D(Texture_ReflectMask).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
 "#endif\n"
 "\n"
 "\n"
 "\n"
 "#ifdef USEGLOW\n"
 "#ifdef USEVERTEXTEXTUREBLEND\n"
-"      color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
+"      color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, offsetMappedTexture2D(Texture_Glow).rgb, terrainblend)) * Color_Glow;\n"
 "#else\n"
-"      color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
+"      color.rgb += half3(offsetMappedTexture2D(Texture_Glow).rgb) * Color_Glow;\n"
 "#endif\n"
 "#endif\n"
 "\n"
 "      // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
 "#ifdef USEREFLECTION\n"
 "      float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
-"      //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
+"      //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(offsetMappedTexture2D(Texture_Normal).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
 "      float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
-"      float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
+"      float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(offsetMappedTexture2D(Texture_Normal).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
 "      // FIXME temporary hack to detect the case that the reflection\n"
 "      // gets blackened at edges due to leaving the area that contains actual\n"
 "      // content.\n"
index 7344888..bb7d13f 100644 (file)
--- a/vid_sdl.c
+++ b/vid_sdl.c
@@ -1211,6 +1211,7 @@ void wrapglAttachShader(GLuint containerObj, GLuint obj) {glAttachShader(contain
 void wrapglBegin(GLenum mode) {Con_Printf("glBegin(mode)\n");}
 //void wrapglBeginQuery(GLenum target, GLuint qid) {glBeginQuery(target, qid);}
 void wrapglBindAttribLocation(GLuint programObj, GLuint index, const GLchar *name) {glBindAttribLocation(programObj, index, name);}
+void wrapglBindFragDataLocation(GLuint programObj, GLuint index, const GLchar *name) {glBindFragDataLocation(programObj, index, name);}
 void wrapglBindBuffer(GLenum target, GLuint buffer) {glBindBuffer(target, buffer);}
 void wrapglBindFramebuffer(GLenum target, GLuint framebuffer) {glBindFramebuffer(target, framebuffer);}
 void wrapglBindRenderbuffer(GLenum target, GLuint renderbuffer) {glBindRenderbuffer(target, renderbuffer);}
@@ -1432,6 +1433,7 @@ void GLES_Init(void)
        qglBegin = wrapglBegin;
 //     qglBeginQueryARB = wrapglBeginQuery;
        qglBindAttribLocation = wrapglBindAttribLocation;
+       qglBindFragDataLocation = wrapglBindFragDataLocation;
        qglBindBufferARB = wrapglBindBuffer;
        qglBindFramebufferEXT = wrapglBindFramebuffer;
        qglBindRenderbufferEXT = wrapglBindRenderbuffer;
index 8eda95e..43d5e69 100644 (file)
@@ -335,6 +335,7 @@ void (GLAPIENTRY *qglVertexAttribPointer)(GLuint index, GLint size, GLenum type,
 void (GLAPIENTRY *qglEnableVertexAttribArray)(GLuint index);
 void (GLAPIENTRY *qglDisableVertexAttribArray)(GLuint index);
 void (GLAPIENTRY *qglBindAttribLocation)(GLuint programObj, GLuint index, const GLchar *name);
+void (GLAPIENTRY *qglBindFragDataLocation)(GLuint programObj, GLuint index, const GLchar *name);
 void (GLAPIENTRY *qglGetActiveAttrib)(GLuint programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
 GLint (GLAPIENTRY *qglGetAttribLocation)(GLuint programObj, const GLchar *name);
 void (GLAPIENTRY *qglGetVertexAttribdv)(GLuint index, GLenum pname, GLdouble *params);
@@ -726,6 +727,12 @@ static dllfunction_t gl20shaderfuncs[] =
        {NULL, NULL}
 };
 
+static dllfunction_t glsl130funcs[] =
+{
+       {"glBindFragDataLocation", (void **) &qglBindFragDataLocation},
+       {NULL, NULL}
+};
+
 static dllfunction_t vbofuncs[] =
 {
        {"glBindBufferARB"    , (void **) &qglBindBufferARB},
@@ -828,6 +835,9 @@ void VID_CheckExtensions(void)
                Sys_Error("OpenGL 1.1.0 functions not found");
        vid.support.gl20shaders = GL_CheckExtension("2.0", gl20shaderfuncs, "-noshaders", false);
 
+       // this one is purely optional, needed for GLSL 1.3 support (#version 130), so we don't even check the return value of GL_CheckExtension
+       GL_CheckExtension("2.0", glsl130funcs, "-noglsl130", false);
+
        CHECKGLERROR
 
        Con_DPrint("Checking OpenGL extensions...\n");