After updating driver OpenGL app has broken
I was developing FFT ocean demo. After updating driver (up to 9.12) it has broken. The problem occurs if my vertex shader fetches height from height map and pixel shader fetches from cubemap. If I disable one of this condition everything works fine.
I am sure I have set up textures to different stages, but it seems that VS tries to fetch from cubemap (Relief of cube map side can be seen on the water surface). I also tried this shaders in Render Monkey and the result is the same.
I used Radeon HD 3870, Radeon HD 4850. I haven't such problem with catalyst 9.11 and with 9.10.
Here is vertex shader:
uniform sampler2D heightMap;
uniform float sharpness;
uniform vec2 surfaceSize; // size of the waterSurface
uniform vec3 surfaceCorners[4];
uniform vec4 lightPosition;
uniform vec4 eyePosition;
uniform float distanceSmoothness;
uniform mat4 projectionMatrix;
uniform mat4 worldViewMatrix;
uniform mat4 reflectionMatrix;
varying vec2 normalTexCoord;
varying vec3 eyeDir;
varying vec3 fragmentPosition;
#ifdef ENABLE_REFLECTIONS
varying vec2 reflectionTexCoord;
#endif
void main()
{
// calculate vertex position
vec3 a = (surfaceCorners[2] - surfaceCorners[3]) * gl_Vertex.y;
vec3 b = (surfaceCorners[1] - surfaceCorners[0]) * gl_Vertex.y;
vec3 c = mix(b, a, gl_Vertex.x);
vec3 d = (surfaceCorners[3] - surfaceCorners[0]) * gl_Vertex.x;
vec4 waterVertex = vec4(surfaceCorners[0] + c + d, 1.0);
// calculate texture coordinates
normalTexCoord = waterVertex.xz / surfaceSize;
// displace water vertex using height map with edge & distance attenuation
float distance = length( (worldViewMatrix * waterVertex).xyz );
float distanceAttenuation = exp(-fragmentPosition.z * distanceSmoothness);
float attenuation = distanceAttenuation * min( pow(1.0 - gl_Vertex.y, 0.2), pow(1.0 - abs(gl_Vertex.x - 0.5) * 2.0, 0.2) );
vec4 texel = texture2D(heightMap, normalTexCoord);
waterVertex.y = texel.x * attenuation;
waterVertex.xz -= sharpness * texel.zw * attenuation;
eyeDir = waterVertex.xyz - eyePosition.xyz;
#ifdef ENABLE_REFLECTIONS
vec4 projTexCoord = reflectionMatrix * waterVertex;
reflectionTexCoord = projTexCoord.xy / projTexCoord.w;
#endif
gl_Position = projectionMatrix * worldViewMatrix * waterVertex;
fragmentPosition = vec3(gl_Position.xy / gl_Position.w, gl_Position.w);
}
And fragment shader:
//uniform sampler2D heightMap;
uniform sampler2D normalMap;
uniform sampler2D reflectMap;
uniform sampler2D depthMap;
uniform sampler2D refractMap;
uniform samplerCube environmentMap;
uniform float distanceFogginess;
uniform float distanceSmoothness;
uniform float waterTransparency;
uniform vec4 fogColor;
uniform vec4 lightSpecular;
// inverted projection transform to restore depth from the z-buffer
uniform mat2 projectionMatrixInverse;
varying vec2 normalTexCoord;
varying vec3 eyeDir;
varying vec3 fragmentPosition;
#ifdef ENABLE_REFLECTIONS
varying vec2 reflectionTexCoord;
#endif
float get_fragment_depth(sampler2D depthMap, vec2 fragmentPosition, vec2 texCoord)
{
float depth = 2.0 * texture2D(depthMap, texCoord).r - 1.0;
vec2 vec = projectionMatrixInverse * vec2(depth, 1.0);
return vec.x / vec.y;
}
void main()
{
const vec3 waterMinColor = vec3(0.0, 0.05, 0.15);
const vec3 waterMaxColor = vec3(0.0, 0.1, 0.15);
vec3 eyeDirNorm = normalize(eyeDir);
vec3 normalNorm = 2.0 * ( texture2D(normalMap, normalTexCoord).rgb - vec3(0.5) );
// distance attenuation of light and fogginess
float distVal = exp(-fragmentPosition.z * distanceFogginess);
normalNorm = mix( vec3(0.0, 1.0, 0.0), normalNorm, pow(distVal, 5.0) );
float dotValue = dot(eyeDirNorm, normalNorm);
vec3 waterColor = mix( waterMinColor, waterMaxColor, abs(dotValue) );
// texture coordinate of the fragment
vec2 fragTexCoord = 0.5 * fragmentPosition.xy + vec2(0.5);
#ifdef ENABLE_REFRACTIONS
{
vec2 distortTexCoord = fragTexCoord + normalNorm.xz * 0.02;
#ifdef ENABLE_DEPTH_MAP
float nonDistortDepth = get_fragment_depth(depthMap, fragmentPosition.xy, fragTexCoord);
float distortDepth = get_fragment_depth(depthMap, fragmentPosition.xy, distortTexCoord);
// calculate distorsion
float deltaDepth;
if (distortDepth > fragmentPosition.z) {
deltaDepth = distortDepth - fragmentPosition.z;
}
else
{
distortTexCoord = fragTexCoord;
deltaDepth = nonDistortDepth - fragmentPosition.z;
}
// calculate attenuation
float depthAttenuation = 1.0 / pow(1.0 + deltaDepth, 1.0 / waterTransparency - 1.0);
// mix water with reflections
vec4 refractColor = texture2D(refractMap, distortTexCoord).rgba;
waterColor = mix(waterColor, refractColor.rgb, depthAttenuation * refractColor.a);
#else
vec4 refractColor = texture2D(refractMap, distortTexCoord).rgba;
waterColor = mix(waterColor, refractColor.rgb, waterTransparency * refractColor.a);
#endif
}
#endif
float fresnel = clamp( pow(1.0 + dotValue, 4.0), 0.05, 0.5 );
vec3 reflectColor = textureCube( environmentMap, reflect(eyeDirNorm, normalNorm) ).rgb;
#ifdef ENABLE_REFLECTIONS
{
vec2 distortTexCoord = reflectionTexCoord + normalNorm.xz * 0.05;
vec4 localReflectColor = texture2DLod(reflectMap, distortTexCoord, 2.0).rgba;
reflectColor = mix(reflectColor, localReflectColor.rgb, localReflectColor.a);
}
#endif
waterColor = mix(waterColor, reflectColor, fresnel);
waterColor = mix(fogColor.rgb, waterColor, distVal);
gl_FragColor = vec4(waterColor, 1.0);
}