Underwater Effect

The example script in this article simulates the type of visual distortion that occurs in an underwater scene. It uses a custom post-process effect created using Vizard's vizfx.postprocess library and GLSL (OpenGL shading language).

Refer to the vizfx.postprocess documention in the Vizard Help for a description of all Vizard's built-in effects. The documentation also shows the basics for creating a simple custom effect. Custom effects, like the one in this article, can be created if you have some knowledge of GLSL.



import viz
import vizconfig
viz.go()

viz.add('piazza.osgb')

from vizfx.postprocess.effect import BaseShaderEffect
import vizfx.postprocess

class UnderwaterEffect(BaseShaderEffect):

def __init__(self, speed=2.0, scale=2.0, density=20.0, **kw):
self._speed = speed
self._scale = scale
self._density = density
BaseShaderEffect.__init__(self,**kw)

def _getFragmentCode(self):
return """
        uniform sampler2D vizpp_InputTex;
        uniform float osg_FrameTime;
        uniform float speed;
        uniform float scale;
        uniform float density;
        void main()
        {
            vec2 uv = gl_TexCoord[0].xy;

            //bumpUV.y = fract(bumpUV.y - osg_FrameTime*0.1);
            vec2 dt;
            dt.x = sin(speed*osg_FrameTime+uv.y*density)*0.001*scale;
            dt.y = cos(0.7+0.7*speed*osg_FrameTime+uv.x*density)*0.001*scale;

            gl_FragColor = texture2D(vizpp_InputTex,uv+dt);
        }
        """

def _createUniforms(self):
self.uniforms.addFloat('speed',self._speed)
self.uniforms.addFloat('scale',self._scale)
self.uniforms.addFloat('density',self._density)

def setSpeed(self,speed):
self._speed = speed
self.uniforms.setValue('speed',speed)

def getSpeed(self):
return self._speed

def setScale(self,scale):
self._scale = scale
self.uniforms.setValue('scale',scale)

def getScale(self):
return self._scale

def setDensity(self,density):
self._density = density
self.uniforms.setValue('density',density)

def getDensity(self):
return self._density

def createConfigUI(self):
"""Implement configurable interface"""
ui = BaseShaderEffect.createConfigUI(self)
ui.addFloatRangeItem('Speed',[0.0,10.0],fset=self.setSpeed,fget=self.getSpeed)
ui.addFloatRangeItem('Scale',[0.0,10.0],fset=self.setScale,fget=self.getScale)
ui.addFloatRangeItem('Density',[0.0,100.0],fset=self.setDensity,fget=self.getDensity)
return ui

effect = UnderwaterEffect()
vizfx.postprocess.addEffect(effect)
vizconfig.register(effect)
vizconfig.getConfigWindow().setWindowVisible(True)

Add some fog to the script to give the scene a blue water color and reduce the visibility of objects in the distance. Try changing the values used in these commands to get different levels of green/blue color and murkiness in the water:

viz.fog(0.2)
viz.fogcolor(0,0,0.5)