Depth of Field Effect


(Posted 11 months ago) RonTek

Yet another DOF implementation. Some parts and the shader code was ported from the Max3D showcase here where the skybox is also affected. This is a wip so it needs a bit of cleaning up and the viewport setting is also hardcoded, just need to change and use shader params to go with your screen resolution. Other params are also in place to fine tune and fit to your scene.

dof.vert.glsl


varying vec4 vertColor;
varying vec2 texCoords;
varying vec4 texCoord1;

void main(){
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
    vertColor = gl_Color;
    texCoords = gl_TexCoord[0].st;
    texCoord1 = gl_TextureMatrix[1] * gl_MultiTexCoord1;
}

dof.frag.glsl


varying vec2 texCoords;

varying vec4 texCoord1;

uniform sampler2D depthtex;
uniform sampler2D colortex;

uniform float minblur; 
uniform float maxblur;
float center = 0.0;

float bb_zNear = 0.5;
float bb_zFar = 1000.0;
vec2 bb_ViewportSize = vec2(800.0 /600.0);

uniform float blursize;

void main ()
{ 

    float x = texCoords.x;
    float y = texCoords.y;

    vec4 pixel = texture2D(colortex, texCoords);

    vec4 blurFactor = texture2D(depthtex, texCoord1.st) * blursize;
    float bf = blurFactor.r;
    vec4 blurSample = vec4(0.0,0.0,0.0,0.0);

    int lo = 2; // 2
    int hi = 3; // 3
    for(int tx =-lo; tx maxblur)
    {
        fragz = maxblur;
    }
    else
    {
        if (fragz < minblur)
        {
            fragz = minblur;
        }
    }

    float mx = 0.0;
    float div; // Distance from world at center pixel to min/max distance...

    if (fragz > center)
    {
        div = 1.0 / (maxblur - center);
        mx = (fragz - center) * div;
    }
    else
    {
        div = 1.0 / (center - minblur);
        mx = (center - fragz) * div;
    }

    pixel = mix (pixel, blurSample, mx);

    if (int (texCoords.x) == bb_ViewportSize.x && int (texCoords.y) == bb_ViewportSize.y)
    {
        pixel = vec4 (1.0, 1.0, 1.0, 1.0);
    }

    gl_FragColor = pixel;

}

DepthOfField.bmx


' depthoffield.bmx
' postprocess effect - render framebuffer and depthbuffer to shader textures for depth of field

Strict

Framework Openb3dMax.B3dglgraphics
Import Brl.Random

Local width%=800,height%=600

Graphics3D width,height,0,2

SeedRnd MilliSecs()
ClearTextureFilters ' remove mipmap flag for postfx texture

Global Camera:TCamera=CreateCamera()
CameraRange Camera,0.5,5000.0 ' near must be closer than screen sprite to prevent clipping
CameraClsColor Camera,150,200,250

Global postfx_cam:TCamera=CreateCamera() ' copy main camera
CameraRange postfx_cam,0.5,1000.0
CameraClsColor postfx_cam,150,200,250
HideEntity postfx_cam

Local Light:TLight=CreateLight()
PositionEntity Light,5,5,5

Local skymap:String="../media/envmap_cube.jpg"
Local pix:TPixmap=LoadPixmap(skymap)
Local framesize%=PixmapHeight(pix)/2 ' 3 * 2 cubemap layout

'Local skybox:TMesh=LoadCubicSkyBox( skymap,1+16+32,framesize,framesize,4,5,6,7,9,1 ) ' lf-x, fr+z, rt+x, bk-z, dn-y, up+y

Local skybox:TMesh=LoadCubicSkyBox( skymap,1+16+32,framesize,framesize,0,5,2,1,3,4 ) ' lf-x, fr+z, rt+x, bk-z, dn-y, up+y

ScaleMesh skybox,500,500,500
PositionEntity skybox,0,50,0
EntityFX skybox,1

Local sphere:TMesh
Local s_tex1:TTexture=LoadTexture("../media/tmp27.jpg",1+8)
Local s_tex2:TTexture=LoadTexture("../media/water.bmp",1+8)
Local s_tex3:TTexture=LoadTexture("../media/Moss.bmp",1+8)
For Local r:Int=0 To 6
    For Local t:Int=-2 To 2
        sphere=CreateSphere()
        PositionEntity sphere,(t*4),1,(t*4)+((r-2)*8)
        If r Mod 3=1 EntityTexture sphere,s_tex1
        If r Mod 3=2 EntityTexture sphere,s_tex2
        If r Mod 3=0 EntityTexture sphere,s_tex3
    Next
Next

Local cube:TMesh=LoadMesh("../media/wcrate1.3ds")
ScaleMesh cube,0.15,0.15,0.15
PositionEntity cube,0,8,40
Local cube_tex:TTexture=LoadTexture("../media/crate.bmp",1+8)
EntityTexture cube,cube_tex

Global colortex:TTexture=CreateTexture(width,height,1+256)
Global depthtex:TTexture=CreateTexture(width,height,1+256)
ScaleTexture colortex,1.0,-1.0
ScaleTexture depthtex,1.0,-1.0

' in GL 2.0 render textures need attached before other textures (EntityTexture)
CameraToTex colortex,Camera
DepthBufferToTex depthtex,Camera
TGlobal.CheckFramebufferStatus(GL_FRAMEBUFFER_EXT) ' check for framebuffer errors

' screen sprite - by BlitzSupport
Global screensprite:TSprite=CreateSprite()
ScaleSprite screensprite,1.0,Float( GraphicsHeight() ) / GraphicsWidth() ' 0.75
EntityOrder screensprite,-1
EntityParent screensprite,Camera
MoveEntity screensprite,0,0,1.0 ' set z to 1.0

Global screensprite2:TSprite=CreateSprite()
ScaleSprite screensprite2,1.0,Float( GraphicsHeight() ) / GraphicsWidth() ' 0.75
EntityOrder screensprite2,-1
EntityParent screensprite2,Camera
MoveEntity screensprite2,0,0,1.0 ' set z to 1.0
EntityTexture screensprite2,depthtex

PositionEntity Camera,0,3,0 ' move camera now sprite is parented to it
MoveEntity Camera,0,0,-25

Local ground:TMesh=CreatePlane(128)
Local ground_tex:TTexture=LoadTexture("../media/Envwall.bmp")
EntityTexture ground,ground_tex

Local shader:TShader=LoadShader("","../glsl/dof.vert.glsl","../glsl/dof.frag.glsl")
ShaderTexture(shader,colortex,"colortex",0) ' 0 is render texture
ShaderTexture(shader,depthtex,"depthtex",1) ' 1 is depth texture
Local blursize#=0.0030,minblur#=2.0,maxblur#=50.00
UseFloat(shader,"blursize",blursize)
UseFloat(shader,"minblur",minblur)
UseFloat(shader,"maxblur",maxblur)
UseFloat(

ShadeEntity(screensprite,shader)

Global postprocess%=1

' fps code
Local old_ms%=MilliSecs()
Local renders%, fps%

While Not KeyDown(KEY_ESCAPE)

    If KeyHit(KEY_SPACE) Then postprocess:+1 ; If postprocess>2 Then postprocess=0

    If KeyDown(KEY_EQUALS)  Then blursize:+0.0001
    If KeyDown(KEY_MINUS)  Then blursize:-0.0001

    If KeyDown(KEY_CLOSEBRACKET)  Then maxblur:+1
    If KeyDown(KEY_OPENBRACKET)  Then maxblur:-1

    If KeyDown(KEY_0)  Then minblur:+1
    If KeyDown(KEY_9)  Then minblur:-1

    ' control camera
    MoveEntity Camera,KeyDown(KEY_D)-KeyDown(KEY_A),0,KeyDown(KEY_W)-KeyDown(KEY_S)
    TurnEntity Camera,KeyDown(KEY_DOWN)-KeyDown(KEY_UP),KeyDown(KEY_LEFT)-KeyDown(KEY_RIGHT),0

    PositionEntity postfx_cam,EntityX(Camera),EntityY(Camera),EntityZ(Camera)
    RotateEntity postfx_cam,EntityPitch(Camera),EntityYaw(Camera),EntityRoll(Camera)

    PositionEntity skybox,EntityX(Camera),EntityY(Camera),EntityZ(Camera)

    TurnEntity cube,0.1,0.2,0.3
    'TurnEntity pivot,0,1,0

    UpdateWorld
    UpdateDepthPass()

    ' calculate fps
    renders=renders+1
    If MilliSecs()-old_ms>=1000
        old_ms=MilliSecs()
        fps=renders
        renders=0
    EndIf

    Text 0,20,"FPS: "+fps
    Text 0,40,"Space: postprocess = "+postprocess+", +/-: blursize = "+blursize +", [/]: maxblur = "+maxblur+", (/): minblur = "+minblur

    Flip

Wend
End

Function UpdateDepthPass()

    If postprocess=0
        HideEntity postfx_cam
        ShowEntity Camera
        HideEntity screensprite2
        HideEntity screensprite

        RenderWorld
    ElseIf postprocess=1 ' 2 pass depth
        HideEntity Camera
        ShowEntity postfx_cam
        HideEntity screensprite2
        HideEntity screensprite

        CameraToTex colortex,postfx_cam

        HideEntity postfx_cam
        ShowEntity Camera

        DepthBufferToTex depthtex,Camera

        ShowEntity screensprite

        RenderWorld
    ElseIf postprocess=2 ' depth
        HideEntity Camera
        ShowEntity postfx_cam
        HideEntity screensprite2
        HideEntity screensprite

        DepthBufferToTex depthtex,postfx_cam

        ShowEntity screensprite2
        HideEntity postfx_cam
        ShowEntity Camera

        RenderWorld
    EndIf

End Function

' Create skybox from the same cubemap image
Function LoadCubicSkyBox:TMesh( file$, flags%, width%, height%, lf%, fr%, rt%, bk%, dn%, up% )

    Local t:TTexture, b:TBrush, s:TSurface
    Local m:TMesh=CreateMesh()

    'top face
    t=LoadAnimTexture( file$,flags,width,height,up,1 ) ' load single frame of same anim texture
    b=CreateBrush()
    BrushTexture b,t
    s=CreateSurface( m,b )
    AddVertex s,-1,+1,+1,0,1
    AddVertex s,+1,+1,+1,1,1
    AddVertex s,+1,+1,-1,1,0
    AddVertex s,-1,+1,-1,0,0
    AddTriangle s,0,1,2
    AddTriangle s,0,2,3
    FreeBrush b

    'left face
    t=LoadAnimTexture( file$,flags,width,height,lf,1 )
    b=CreateBrush()
    BrushTexture b,t
    s=CreateSurface( m,b )
    AddVertex s,-1,+1,+1,1,0
    AddVertex s,-1,+1,-1,0,0
    AddVertex s,-1,-1,-1,0,1
    AddVertex s,-1,-1,+1,1,1
    AddTriangle s,0,1,2
    AddTriangle s,0,2,3
    FreeBrush b

    'front face
    t=LoadAnimTexture( file$,flags,width,height,fr,1 )
    b=CreateBrush()
    BrushTexture b,t
    s=CreateSurface( m,b )
    AddVertex s,+1,+1,+1,1,0 ' ul
    AddVertex s,-1,+1,+1,0,0 ' ur
    AddVertex s,-1,-1,+1,0,1 ' dr
    AddVertex s,+1,-1,+1,1,1 ' dl
    AddTriangle s,0,1,2
    AddTriangle s,0,2,3 
    FreeBrush b

    'right face
    t=LoadAnimTexture( file$,flags,width,height,rt,1 )
    b=CreateBrush()
    BrushTexture b,t
    s=CreateSurface( m,b )
    AddVertex s,+1,+1,-1,1,0
    AddVertex s,+1,+1,+1,0,0
    AddVertex s,+1,-1,+1,0,1
    AddVertex s,+1,-1,-1,1,1
    AddTriangle s,0,1,2
    AddTriangle s,0,2,3
    FreeBrush b

    'back face
    t=LoadAnimTexture( file$,flags,width,height,bk,1 )
    b=CreateBrush()
    BrushTexture b,t
    s=CreateSurface( m,b )
    AddVertex s,-1,+1,-1,1,0
    AddVertex s,+1,+1,-1,0,0
    AddVertex s,+1,-1,-1,0,1
    AddVertex s,-1,-1,-1,1,1
    AddTriangle s,0,1,2
    AddTriangle s,0,2,3
    FreeBrush b

    'down face
    t=LoadAnimTexture( file$,flags,width,height,dn,1 )
    b=CreateBrush()
    BrushTexture b,t
    s=CreateSurface( m,b )
    AddVertex s,-1,-1,-1,0,1 ' dl
    AddVertex s,+1,-1,-1,1,1 ' dr
    AddVertex s,+1,-1,+1,1,0 ' ur
    AddVertex s,-1,-1,+1,0,0 ' ul
    AddTriangle s,0,1,2
    AddTriangle s,0,2,3
    FreeBrush b

    FlipMesh m
    Return m

End Function
(Posted 11 months ago) markcwm commented:

Woot! Thanks Ron, there's no harm in 2 versions of something. Well, can't wait to try this out.

(Posted 11 months ago) RonTek commented:

Sure thing Mark! Yes and this should work with the latest version and NG. cheers.

(Posted 6 months ago) markcwm commented:

Hi Ron,

I've added this to openb3dmax.docs now and yes this is a much better version than what I had, which is just all blurred with no sharpness near the camera, and the framerate is exactly the same, I still have the old one in there too but there's no need for it now so I should probably just remove it.

(Posted 6 months ago) RonTek commented:

cool beans Mark I like this method as well and should be useful in all sort of games/scenes.

Reply To Topic

Please log in to reply