Ticket #3781: water.diff

File water.diff, 17.7 KB (added by aeonios, 8 years ago)
  • binaries/data/mods/public/shaders/glsl/water_high.fs

     
    127127}
    128128
    129129void main()
    130 {
    131     //gl_FragColor = texture2D(waterEffectsTex, gl_FragCoord.xy/screenSize);
    132     //return;
    133    
     130{   
    134131    float fresnel;
    135     float t;                // Temporary variable
    136132    vec2 reflCoords, refrCoords;
    137133    vec3 reflColor, refrColor, specular;
    138     float losMod;
     134    float losMod, reflMod;
    139135   
    140     vec3 l = -sunDir;
    141136    vec3 v = normalize(cameraPos - worldPos);
    142     vec3 h = normalize(l + v);
    143137   
    144138    // Calculate water normals.
    145139
     
    147141    float baseScale = waveParams1.g;
    148142    float flattenism = waveParams1.b;
    149143    float baseBump = waveParams1.a;
    150 
    151     float smallIntensity = waveParams2.r;
    152     float smallBase = waveParams2.g;
    153144    float BigMovement = waveParams2.b;
    154     float SmallMovement = waveParams2.a;
    155145   
    156146    float moddedTime = mod(time * 60.0, 8.0) / 8.0;
    157147   
    158148    // This method uses 60 animated water frames. We're blending between each two frames
    159     // TODO: could probably have fewer frames thanks to this blending.
    160149    // Scale the normal textures by waviness so that big waviness means bigger waves.
    161150    vec3 ww1 = texture2D(normalMap, (normalCoords.st + normalCoords.zw * BigMovement*waviness/10.0) * (baseScale - waviness/wavyEffect)).xzy;
    162151    vec3 ww2 = texture2D(normalMap2, (normalCoords.st + normalCoords.zw * BigMovement*waviness/10.0) * (baseScale - waviness/wavyEffect)).xzy;
     
    165154    ww1.x = wwInterp.x * WindCosSin.x - wwInterp.z * WindCosSin.y;
    166155    ww1.z = wwInterp.x * WindCosSin.y + wwInterp.z * WindCosSin.x;
    167156    ww1.y = wwInterp.y;
    168    
    169     vec3 smallWW = texture2D(normalMap, (normalCoords.st + normalCoords.zw * SmallMovement*waviness/10.0) * baseScale*3.0).xzy;
    170     vec3 smallWW2 = texture2D(normalMap2, (normalCoords.st + normalCoords.zw * SmallMovement*waviness/10.0) * baseScale*3.0).xzy;
    171     vec3 smallWWInterp = mix(smallWW, smallWW2, moddedTime) - vec3(0.5,0.0,0.5);
    172 
    173     smallWW.x = smallWWInterp.x * WindCosSin.x - smallWWInterp.z * WindCosSin.y;
    174     smallWW.z = smallWWInterp.x * WindCosSin.y + smallWWInterp.z * WindCosSin.x;
    175     smallWW.y = smallWWInterp.y;
    176 
    177     ww1 += vec3(smallWW)*(fwaviness/10.0*smallIntensity + smallBase);
    178    
    179     ww1 = mix(smallWW, ww1, waterInfo.r);
    180157       
    181158    // Flatten them based on waviness.
    182159    vec3 n = normalize(mix(vec3(0.0,1.0,0.0),ww1, clamp(baseBump + fwaviness/flattenism,0.0,1.0)));
     
    189166        n = mix(vec3(0.0,1.0,0.0), n,0.5 + waterInfo.r/2.0);
    190167    #endif
    191168
    192     n = vec3(-n.x,n.y,-n.z);
     169    n = vec3(-n.x,n.y,-n.z); // The final wave normal vector.
    193170   
    194     // simulates how parallel the "point->sun", "view->point" vectors are.
    195     float ndoth = dot(n , h);
    196    
    197     // how perpendicular to the normal our view is. Used for fresnel.
     171    // How perpendicular to the normal our view is. Used for fresnel.
    198172    float ndotv = clamp(dot(n, v),0.0,1.0);
    199173   
    200     // diffuse lighting-like. used for shadows?
    201     float ndotl = (dot(n, l) + 1.0)/2.0;
     174    // Fresnel for "how much reflection vs how much refraction".
     175    fresnel = clamp(((pow(1.1 - ndotv, 3.0)) * 1.5), 0.2, 1.0); // Approximation. I'm using 1.1 and not 1.0 because it causes artifacts, see #1714
    202176   
     177    // Specular lighting vectors
     178    vec3 specVector = normalize(reflect(sunDir, n));
     179    float specIntensity = pow(abs(dot(specVector, v)), 256.0);
     180
     181    specular = specIntensity * sunColor * fresnel;
     182   
    203183    float depth;
    204184#if USE_REAL_DEPTH
    205185    // Don't change these two. They should match the values in the config (TODO: dec uniforms).
     
    238218    depth = max(depth,fancyeffects.a);
    239219#endif
    240220   
    241     // Fresnel for "how much reflection vs how much refraction".
    242     // Since we're not trying to simulate a realistic ocean 100%, aim for something that gives a little too much reflection
    243     // because we're not used to seeing the see from above.
    244     fresnel = clamp(pow(1.05 - ndotv, 1.1),0.0,0.8); // approximation. I'm using 1.05 and not 1.0 because it causes artifacts, see #1714
    245     // multiply by v.y so that in the distance refraction wins.
    246     // TODO: this is a hack because reflections don't work in the distance.
    247     fresnel = clamp(fresnel*1.5,0.0,0.9);
    248     fresnel *= min(1.0,log(1.0 + v.y*5.0));
    249    
    250     //gl_FragColor = vec4(fresnel,fresnel,fresnel,1.0);
    251     //return;
    252    
    253221#if USE_SHADOWS_ON_WATER && USE_SHADOW
    254222    float shadow = get_shadow(vec4(v_shadow.xy, v_shadow.zw));
    255223#endif
     
    256224   
    257225    // for refraction, we want to adjust the value by v.y slightly otherwise it gets too different between "from above" and "from the sides".
    258226    // And it looks weird (again, we are not used to seeing water from above).
    259     float fixedVy = max(v.y,0.1);
     227    float fixedVy = max(v.y,0.01);
    260228   
    261     float distoFactor = clamp(depth/2.0,0.0,7.0);
    262    
    263229    float murky = mix(200.0,0.1,pow(murkiness,0.25));
    264230   
    265231#if USE_REFRACTION
    266     refrCoords = clamp( (0.5*refractionCoords.xy - n.xz * distoFactor*7.0) / refractionCoords.z + 0.5,0.0,1.0); // Unbias texture coords
     232    // distoFactor controls the amount of distortion relative to wave normals.
     233    const float distoFactor = 3.5;
     234   
     235    // Distort the texture coords under where the water is to simulate refraction.
     236    refrCoords = (0.5 * refractionCoords.xy - n.xz * distoFactor) / refractionCoords.z + 0.5;
    267237    vec3 refColor = texture2D(refractionMap, refrCoords).rgb;
    268     if (refColor.r > refColor.g + refColor.b + 0.25)
     238   
     239    // Note, the refraction map is cleared using (255, 0, 0), so pixels outside of the water plane are pure red.
     240    // If we get a pure red fragment, use an undistorted/less distorted coord instead.
     241    if (refColor.r == 1.0)
    269242    {
    270         refrCoords = clamp( (0.5*refractionCoords.xy + n.xz) / refractionCoords.z + 0.5,0.0,1.0);   // Unbias texture coords
     243        refrCoords = (0.5*refractionCoords.xy) / refractionCoords.z + 0.5;
    271244        refColor = texture2D(refractionMap, refrCoords).rgb;
    272245    }
    273246   
    274     // TODO: make murkiness (both types rematter on that.
    275     // linearly extinct the water. This is how quickly we see nothing but the pure water color
     247    // Apply water tint and murk color.
    276248    float extFact = max(0.0,1.0 - (depth*fixedVy/murky));
    277     // This is how tinted the water is, ie how quickly the refracted floor takes the tint of the water
    278249    float ColextFact = max(0.0,1.0 - (depth*fixedVy/murky));
    279250    vec3 colll = mix(refColor*tint,refColor,ColextFact);
    280251   
    281 #if USE_SHADOWS_ON_WATER && USE_SHADOW
    282     // TODO:
    283252    refrColor = mix(color, colll, extFact);
    284253#else
     254    // Apply water tint and murk color only.
     255    float extFact = max(0.0,1.0 - (depth*fixedVy/murky));
     256    float ColextFact = max(0.0,1.0 - (depth*fixedVy/murky));
     257    vec3 colll = mix(color*tint,color,ColextFact);
     258   
    285259    refrColor = mix(color, colll, extFact);
    286260#endif
    287 #else
    288     // linearly extinct the water. This is how quickly we see nothing but the pure water color
    289     float extFact = max(0.0,1.0 - (depth*fixedVy/20.0));
    290     // using both those factors, get our transparency.
    291     // This will be our base transparency on top.
    292     float base = 0.4 + depth*fixedVy/15.0; // TODO: murkiness.
    293     float alphaCoeff = mix(1.0, base, extFact);
    294     refrColor = color;
    295 #endif
    296261   
    297262#if USE_REFLECTION
    298263    // Reflections
    299     // we use real reflections against th skybox, and distort a texture of objects closer.
     264    // We use real reflections against the skybox, and distort a texture of objects closer.
    300265    vec3 eye = reflect(v,n);
    301     //eye.y = min(-0.2,eye.y);
    302     // let's calculate where we intersect with the skycube.
     266   
     267    // Calculate where we intersect with the skycube.
    303268    Ray myRay = Ray(vec3(worldPos.x/4.0,worldPos.y,worldPos.z/4.0),eye);
    304269    vec3 start = vec3(-1500.0 + mapSize/2.0,-100.0,-1500.0 + mapSize/2.0);
    305270    vec3 end = vec3(1500.0 + mapSize/2.0,500.0,1500.0 + mapSize/2.0);
    306271    float tmin = IntersectBox(myRay,start,end);
    307272    vec4 newpos = vec4(-worldPos.x/4.0,worldPos.y,-worldPos.z/4.0,1.0) + vec4(eye * tmin,0.0) - vec4(-mapSize/2.0,worldPos.y,-mapSize/2.0,0.0);
    308     //newpos = normalize(newpos);
    309273    newpos *= skyBoxRot;
    310274    newpos.y *= 4.0;
    311275    reflColor = textureCube(skyCube, newpos.rgb).rgb;
    312    
    313     // Reflections appear more distorted when viewed from a lower angle. Simulate this.
    314     float angleEffect = clamp(1.3 - dot(vec3(0.0,1.0,0.0), v),0.0,1.0);
    315276
    316     reflCoords = clamp( (0.5*reflectionCoords.xy - 40.0 * n.zx * angleEffect) / reflectionCoords.z + 0.5,0.0,1.0);  // Unbias texture coords
     277    // Distort the reflection coords based on waves.
     278    reflCoords = (0.5*reflectionCoords.xy - 15.0 * n.zx) / reflectionCoords.z + 0.5;
    317279    vec4 refTex = texture2D(reflectionMap, reflCoords);
    318     fresnel = clamp(fresnel+refTex.a/3.0,0.0,1.0);
    319     reflColor = refTex.rgb * refTex.a + reflColor*(1.0-refTex.a);
    320280   
     281    // Interpolate between the sky color and nearby objects.
     282    reflColor = mix(reflColor.rgb, refTex.rgb, refTex.a);
     283    // reflMod is used to reduce the intensity of sky reflections, which otherwise are too extreme.
     284    reflMod = max(refTex.a, 0.55);
     285   
    321286#else
    322     // Temp fix for some ATI cards (see irc logs on th 1st of august betwee, fexor and wraitii)
    323     //reflCoords = clamp( (0.5*reflectionCoords.xy - waviness * mix(1.0, 20.0,waviness/10.0) * n.zx) / reflectionCoords.z + 0.5,0.0,1.0);   // Unbias texture coords
    324     //vec3 refTex = texture2D(reflectionMap, reflCoords).rgb;
    325     //reflColor = refTex.rgb;
    326287    reflColor = vec3(0.15, 0.7, 0.82);
    327288#endif
    328289   
    329     // TODO: At very low angles the reflection stuff doesn't really work any more:
    330     // IRL you would get a blur of the sky, but we don't have that precision (would require mad oversampling)
    331     // So tend towards a predefined color (per-map) which looks like what the skybox would look like if you really blurred it.
    332     // The TODO here would be to precompute a band (1x32?) that represents the average color around the map.
    333     // TODO: another issue is that at high distances (half map) the texture blurs into flatness. Using better mipmaps won't really solve it
    334     // So we'll need to stop showing reflections and default to sky color there too.
    335     // Unless maybe waviness is so low that you would see like in a mirror anyways.
    336     //float disttt = distance(worldPos,cameraPos);
    337     //reflColor = mix(vec3(0.5,0.5,0.55), reflColor, clamp(1.0-disttt/600.0*disttt/600.0,0.0,1.0));//clamp(-0.05 + v.y*20.0,0.0,1.0));
    338    
    339     // Specular.
    340     specular = pow(ndoth, mix(5.0,2000.0, clamp(v.y*v.y*2.0,0.0,1.0)))*sunColor * 1.5;// * sunColor * 1.5 * ww.r;
    341    
    342290    losMod = texture2D(losMap, losCoords.st).a;
    343291    losMod = losMod < 0.03 ? 0.0 : losMod;
    344292   
    345     float wavesFresnel = 1.0;
    346    
    347 #if USE_FANCY_EFFECTS
    348     wavesFresnel = mix(1.0-fancyeffects.a,1.0,clamp(depth,0.0,1.0));
    349 #endif
    350    
    351293    vec3 color;
    352294#if USE_SHADOWS_ON_WATER && USE_SHADOW
    353295    float fresShadow = mix(fresnel, fresnel*shadow, 0.05 + murkiness*0.2);
    354     color = mix(refrColor, reflColor, fresShadow * wavesFresnel);
     296    color = mix(refrColor, reflColor, fresShadow);
    355297#else
    356     color = mix(refrColor, reflColor, fresnel * wavesFresnel);
     298    color = mix(refrColor, reflColor, fresnel * reflMod);
    357299#endif
    358300   
    359301#if USE_SHADOWS_ON_WATER && USE_SHADOW
     
    373315    foaminterp *= mix(foam3, foam4, moddedTime);
    374316   
    375317    foam1.x = foaminterp.x * WindCosSin.x - foaminterp.z * WindCosSin.y;
    376     //foam1.z = foaminterp.x * WindCosSin.y + foaminterp.z * WindCosSin.x;
    377     //foam1.y = foaminterp.y;
     318   
    378319    float foam = FoamEffects.r * FoamEffects.a*0.4 + pow(foam1.x*(5.0+waviness),(2.6 - waviness/5.5));
    379     foam *= ndotl;
    380320   
    381     gl_FragColor.rgb = get_fog(color) * losMod + foam * losMod;// + fancyeffects.a * losMod;
     321    gl_FragColor.rgb = get_fog(color) * losMod + foam * losMod;
    382322#else
    383323    gl_FragColor.rgb = get_fog(color) * losMod;
    384324#endif
    385325   
    386 #if !USE_REFRACTION
    387     gl_FragColor.a = clamp(depth*2.0,0.0,1.0) * alphaCoeff;
    388 #else
    389     gl_FragColor.a = clamp(depth*5.0,0.0,1.0);
    390 #endif
     326gl_FragColor.a = 1.0;
    391327   
    392328#if USE_FANCY_EFFECTS
    393329    if (fancyeffects.a < 0.05 && waterDepth < -1.0 )
    394330        gl_FragColor.a = 0.0;
    395331#endif
    396    
    397     //gl_FragColor = vec4(sunColor,1.0);
    398332}
  • source/renderer/Renderer.cpp

     
    11191119    camera.ClipFrustum(CVector4D(0, 1, 0, -wm.m_WaterHeight));
    11201120
    11211121    SViewPort vp;
    1122     vp.m_Height = wm.m_ReflectionTextureSize;
    1123     vp.m_Width = wm.m_ReflectionTextureSize;
     1122    vp.m_Height = wm.m_RefTextureSize;
     1123    vp.m_Width = wm.m_RefTextureSize;
    11241124    vp.m_X = 0;
    11251125    vp.m_Y = 0;
    11261126    camera.SetViewPort(vp);
     
    11551155    camera.ClipFrustum(CVector4D(0, -1, 0, wm.m_WaterHeight + 0.5f));   // add some to avoid artifacts near steep shores.
    11561156
    11571157    SViewPort vp;
    1158     vp.m_Height = wm.m_RefractionTextureSize;
    1159     vp.m_Width = wm.m_RefractionTextureSize;
     1158    vp.m_Height = wm.m_RefTextureSize;
     1159    vp.m_Width = wm.m_RefTextureSize;
    11601160    vp.m_X = 0;
    11611161    vp.m_Y = 0;
    11621162    camera.SetViewPort(vp);
     
    11881188    // Save the model-view-projection matrix so the shaders can use it for projective texturing
    11891189    wm.m_ReflectionMatrix = m_ViewCamera.GetViewProjection();
    11901190
    1191     float vpHeight = wm.m_ReflectionTextureSize;
    1192     float vpWidth = wm.m_ReflectionTextureSize;
     1191    float vpHeight = wm.m_RefTextureSize;
     1192    float vpWidth = wm.m_RefTextureSize;
    11931193
    11941194    SScreenRect screenScissor;
    11951195    screenScissor.x1 = (GLint)floor((scissor[0].X*0.5f+0.5f)*vpWidth);
     
    12711271    // Save the model-view-projection matrix so the shaders can use it for projective texturing
    12721272    wm.m_RefractionMatrix = m_ViewCamera.GetViewProjection();
    12731273
    1274     float vpHeight = wm.m_RefractionTextureSize;
    1275     float vpWidth = wm.m_RefractionTextureSize;
     1274    float vpHeight = wm.m_RefTextureSize;
     1275    float vpWidth = wm.m_RefTextureSize;
    12761276
    12771277    SScreenRect screenScissor;
    12781278    screenScissor.x1 = (GLint)floor((scissor[0].X*0.5f+0.5f)*vpWidth);
  • source/renderer/WaterManager.cpp

     
    9191   
    9292    m_ReflectionTexture = 0;
    9393    m_RefractionTexture = 0;
    94     m_ReflectionTextureSize = 0;
    95     m_RefractionTextureSize = 0;
     94    m_RefTextureSize = 0;
    9695   
    9796    m_ReflectionFbo = 0;
    9897    m_RefractionFbo = 0;
     
    236235        m_FoamTex = texture;
    237236    }
    238237   
    239     m_ReflectionTextureSize = g_Renderer.GetHeight() * 0.66;    // Higher settings give a better result
    240     m_RefractionTextureSize = g_Renderer.GetHeight() * 0.33;    // Lower settings actually sorta look better since it blurs.
     238    // Use screen-sized textures for minimum artifacts.
     239    m_RefTextureSize = g_Renderer.GetHeight();
    241240   
    242     if (round_down_to_pow2(m_ReflectionTextureSize)/m_ReflectionTextureSize < 0.65)
    243         m_ReflectionTextureSize = round_up_to_pow2(m_ReflectionTextureSize);
    244     else
    245         m_ReflectionTextureSize = round_down_to_pow2(m_ReflectionTextureSize);
     241    m_RefTextureSize = round_up_to_pow2(m_RefTextureSize);
    246242   
    247     if (round_down_to_pow2(m_RefractionTextureSize)/m_RefractionTextureSize < 0.7)
    248         m_RefractionTextureSize = round_up_to_pow2(m_RefractionTextureSize);
    249     else
    250         m_RefractionTextureSize = round_down_to_pow2(m_RefractionTextureSize);
    251    
    252243    // Create reflection texture
    253244    glGenTextures(1, &m_ReflectionTexture);
    254245    glBindTexture(GL_TEXTURE_2D, m_ReflectionTexture);
     
    256247    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    257248    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    258249    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
    259     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)m_ReflectionTextureSize, (GLsizei)m_ReflectionTextureSize, 0,  GL_RGBA, GL_UNSIGNED_BYTE, 0);
     250    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)m_RefTextureSize, (GLsizei)m_RefTextureSize, 0,  GL_RGBA, GL_UNSIGNED_BYTE, 0);
    260251   
    261252    // Create refraction texture
    262253    glGenTextures(1, &m_RefractionTexture);
     
    265256    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    266257    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    267258    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
    268     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, (GLsizei)m_RefractionTextureSize, (GLsizei)m_RefractionTextureSize, 0,  GL_RGB, GL_UNSIGNED_BYTE, 0);
     259    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, (GLsizei)m_RefTextureSize, (GLsizei)m_RefTextureSize, 0,  GL_RGB, GL_UNSIGNED_BYTE, 0);
    269260
    270261    // Create depth textures
    271262    glGenTextures(1, &m_ReflFboDepthTexture);
     
    274265    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    275266    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    276267    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    277     glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, (GLsizei)m_ReflectionTextureSize, (GLsizei)m_ReflectionTextureSize, 0,  GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);
     268    glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, (GLsizei)m_RefTextureSize, (GLsizei)m_RefTextureSize, 0,  GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);
    278269   
    279270    glGenTextures(1, &m_RefrFboDepthTexture);
    280271    glBindTexture(GL_TEXTURE_2D, m_RefrFboDepthTexture);
     
    282273    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    283274    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    284275    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    285     glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, (GLsizei)m_RefractionTextureSize, (GLsizei)m_RefractionTextureSize, 0,  GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);
     276    glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, (GLsizei)m_RefTextureSize, (GLsizei)m_RefTextureSize, 0,  GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);
    286277
    287278    // Create the Fancy Effects texture
    288279    glGenTextures(1, &m_FancyTextureNormal);
  • source/renderer/WaterManager.h

     
    103103    // Reflection and refraction textures for fancy water
    104104    GLuint m_ReflectionTexture;
    105105    GLuint m_RefractionTexture;
    106     size_t m_ReflectionTextureSize;
    107     size_t m_RefractionTextureSize;
     106    size_t m_RefTextureSize;
    108107
    109108    // framebuffer objects
    110109    GLuint m_RefractionFbo;