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;
strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
+ // 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";
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);
"#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"
"#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"
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);}
qglBegin = wrapglBegin;
// qglBeginQueryARB = wrapglBeginQuery;
qglBindAttribLocation = wrapglBindAttribLocation;
+ qglBindFragDataLocation = wrapglBindFragDataLocation;
qglBindBufferARB = wrapglBindBuffer;
qglBindFramebufferEXT = wrapglBindFramebuffer;
qglBindRenderbufferEXT = wrapglBindRenderbuffer;
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);
{NULL, NULL}
};
+static dllfunction_t glsl130funcs[] =
+{
+ {"glBindFragDataLocation", (void **) &qglBindFragDataLocation},
+ {NULL, NULL}
+};
+
static dllfunction_t vbofuncs[] =
{
{"glBindBufferARB" , (void **) &qglBindBufferARB},
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");