Sledge, thanks. There are no delta timing issues since I have no tween frames, the gloom texture is taken every frame. I have tested the method I described and it really works, althouh all in all about 4% slower than the current method.
sswift - not exactly sure if you are talking about the blitz window size - there's no way for me to use a square window size since the game is running in fullscreen and usually in a 4:3 ratio. I tried to find a blur function in your code archive entries, unfort. without success. EDIT: just found it, bluring a texture. I will have to try if this is faster. It could easily be faster, even with the overhead (or what's looking like it) because my current blur function takes 7ms for one pass on my machine (additional passes only take about 1ms since readpixel and writepixel is done only once, no matter how many passes).
Ok, here are the two methods that are head on head right now, concerning speed. If anybody can optimize the speed in a relevant amount, do it!
The first method works like this:
It's taking a small render with the Gloom Quad hidden, 128*96 Pixels. This is then blured and then copied to the texture that is used by the gloom quad. Then the Gloom Quad is unhidden and a full resolution game render is performed. Blendmode 3 of the gloom quad that is sticked to the camera, in front of everything else will now produce the gloom Effect.
In a Scene with 500 cubes onscreen I get about 9ms per frame with no gloom and about 24ms with the gloom turned on (hit space to toggle).
Graphics3D 1024,768,32,1
SetBuffer BackBuffer()
camera=CreateCamera()
light=CreateLight()
RotateEntity light,45,45,45
TranslateEntity camera,0,0,-45
CameraRange camera,.001,100
anz=500
Dim s(anz)
For i=0 To anz
s(i)=CreateCube()
PositionEntity s(i),Rnd(-20,20),Rnd(-20,20),Rnd(-20,20)
EntityColor s(i),Rand(255),Rand(255),Rand(255)
Next
gloo_w#=128
gloo_h#=gloo_w#*(Float(GraphicsHeight())/Float(GraphicsWidth())); 0.75
Dim proc_array(gloo_w#,gloo_h#)
tex=CreateTexture(gloo_w#,gloo_w#,256); Or 16 Or 32)
quad=CreateQuad()
PositionEntity quad,EntityX(camera,1),EntityY(camera,1),EntityZ(camera,1),1
EntityTexture quad,tex
EntityFX quad,1
EntityBlend quad,3
TranslateEntity quad,-(1.0/1024.0),(1.0/1024.0),1.0
;EntityColor quad,0,255,0
gloo_wrel#=GraphicsWidth()/gloo_w
gloo_hrel#=GraphicsHeight()/gloo_h
; ************************************ MAIN ***********************************
While KeyDown(1)=0
For i=0 To anz
TurnEntity s(i),1,2,3
Next
If KeyHit(57)
do_gloom=do_gloom +1
If do_gloom>1 Then do_gloom=0
If do_gloom=0 Then
HideEntity quad
EndIf
If do_gloom=1 Then
ShowEntity quad
EntityAlpha quad,0.95 ;1.0
EndIf
EndIf
If do_gloom=1
CameraViewport camera,0,0,gloo_w#,gloo_h#
HideEntity quad
RenderWorld()
quick_blur(gloo_w#,gloo_h#,2)
ShowEntity quad
CopyRect 0,0,gloo_w#,gloo_h#,0,(gloo_w#-gloo_h#)/2,BackBuffer(),TextureBuffer(tex)
CameraViewport camera,0,0,GraphicsWidth(),GraphicsHeight()
EndIf
RenderWorld()
old_tt=tt
tt=MilliSecs()
Text 0,0,tt-old_tt
Text 0,16,do_gloom
Flip 0
Wend
End
Function quick_blur(w,h,passes=1)
If passes<1 Then passes=1
passes=passes-1
SetBuffer BackBuffer()
LockBuffer(BackBuffer())
For j=0 To h-1
For i=0 To w-1
proc_array(i,j)=ReadPixelFast(i,j) ;And $FFFFFF
Next
Next
For dbass=0 To passes
For j=0 To h-1
For i=1 To w-1
proc_array(i,j)=((proc_array(i,j)And $FEFEFF)Shr 1)+((proc_array(i-1,j)And $FEFEFF)Shr 1)
Next
For i=w-2 To 0 Step -1
proc_array(i,j)=((proc_array(i,j)And $FEFEFE)Shr 1)+((proc_array(i+1,j)And $FEFEFE)Shr 1)
Next
Next
For i=0 To w-1
For j=1 To h-1
proc_array(i,j)=((proc_array(i,j)And $FEFEFF)Shr 1)+((proc_array(i,j-1)And $FEFEFF)Shr 1)
Next
For j=h-2 To 0 Step -1
proc_array(i,j)=((proc_array(i,j)And $FEFEFE)Shr 1)+((proc_array(i,j+1)And $FEFEFE)Shr 1)
Next
Next
Next
For j=0 To h-1
For i=0 To w-1
WritePixelFast i,j,proc_array(i,j)
Next
Next
UnlockBuffer(BackBuffer())
End Function
Function CreateQuad(parent=0)
; creates a quad, facing to the right side
mesh=CreateMesh(parent)
surf=CreateSurface(mesh)
v0=AddVertex(surf, -1.0, 1.0,0, 0,0 )
v1=AddVertex(surf, 1.0, 1.0,0, 1,0 )
v2=AddVertex(surf, 1.0, -1.0,0, 1,1 )
v3=AddVertex(surf, -1.0, -1.0,0, 0,1 )
AddTriangle(surf,v0,v1,v2)
AddTriangle(surf,v0,v2,v3)
UpdateNormals mesh
Return mesh
End Function
Now method 2 that I described eariler actually works like this:
Render the Scene in full game resolution, as usual. Then save a copy of the backbuffer in an imagebuffer. Then use a special trick to quickly scale the backbuffer to 128*96 Pixels. This trick is using Copyrect. It's fast, but not very accurate. However, after bluring the result is about the same as the method with the small extra render. Ok, then blur this 128*96 pixels on the backbuffer, then move them to a texture that is used by the gloom quad. Then restore the backbuffer that was saved in an imagebuffer before. Now hide the main game camera and unhide a special gloom camera that is located far away from any geometry of the scene. The gloom quad is also located there, adjusted to the gloom camera. The gloom camera is using a clsmode that won't clear the background. So we still have the last full render as background. The gloom cam will now render only one quad, with the old the background.
This method is slighty slower than the first one, but it has some potential, because one of the two renders has a very easy job (onyl one quad). At the other hand both renders are fullscreen renders, compared to the first method that is using a 128*96 pixels render for the second one.
My machine takes about 9ms without gloom and 25ms with gloom, as you can see, this is only one millisecond more than the other method.
Graphics3D 1024,768,32,1
SetBuffer BackBuffer()
gloomcam=CreateCamera()
CameraClsMode gloomcam,0,1
CameraRange gloomcam,1,10
PositionEntity gloomcam,30000,0,30000
HideEntity gloomcam
camera=CreateCamera()
light=CreateLight()
RotateEntity light,45,45,45
TranslateEntity camera,0,0,-45
CameraRange camera,.001,100
anz=500
Dim s(anz)
For i=0 To anz
s(i)=CreateCube()
PositionEntity s(i),Rnd(-20,20),Rnd(-20,20),Rnd(-20,20)
EntityColor s(i),Rand(255),Rand(255),Rand(255)
Next
gloo_w#=128
gloo_h#=gloo_w#*(Float(GraphicsHeight())/Float(GraphicsWidth())); 0.75
Dim proc_array(gloo_w#,gloo_h#)
tex=CreateTexture(gloo_w#,gloo_w#,256); Or 16 Or 32)
quad=CreateQuad()
PositionEntity quad,EntityX(gloomcam,1),EntityY(gloomcam,1),EntityZ(gloomcam,1),1
EntityTexture quad,tex
EntityFX quad,1
EntityBlend quad,3
TranslateEntity quad,-(1.0/1024.0),(1.0/1024.0),1.0
EntityParent quad, gloomcam
;EntityColor quad,0,255,0
gloo_wrel#=GraphicsWidth()/gloo_w
gloo_hrel#=GraphicsHeight()/gloo_h
gloombuffer=CreateImage(GraphicsWidth(),GraphicsHeight())
; ************************************ MAIN ***********************************
While KeyDown(1)=0
For i=0 To anz
TurnEntity s(i),1,2,3
Next
If KeyHit(57)
do_gloom=do_gloom +1
If do_gloom>1 Then do_gloom=0
If do_gloom=0 Then
HideEntity quad
HideEntity gloomcam
EndIf
If do_gloom=1 Then
ShowEntity quad
EntityAlpha quad,0.95 ;1.0
EndIf
EndIf
RenderWorld()
If do_gloom=1
CopyRect 0,0,GraphicsWidth(),GraphicsHeight(),0,0,BackBuffer(),ImageBuffer(gloombuffer)
i=0
ifloat#=0
For ifloat=0 To GraphicsWidth() Step 0.0001
CopyRect ifloat,0,1,GraphicsHeight(),i,0,BackBuffer(),BackBuffer()
ifloat=ifloat+gloo_wrel#
i=i+1
Next
i=0
ifloat#=0
For ifloat=0 To GraphicsHeight() Step 0.0001
CopyRect 0,ifloat,GraphicsWidth(),1,0,i,BackBuffer(),BackBuffer()
ifloat=ifloat+gloo_hrel#
i=i+1
Next
quick_blur(gloo_w#,gloo_h#,2)
CopyRect 0,0,gloo_w#,gloo_h#,0,(gloo_w#-gloo_h#)/2,BackBuffer(),TextureBuffer(tex)
CopyRect 0,0,GraphicsWidth(),GraphicsHeight(),0,0,ImageBuffer(gloombuffer),BackBuffer()
HideEntity camera
ShowEntity gloomcam
RenderWorld()
ShowEntity camera
HideEntity gloomcam
EndIf
old_tt=tt
tt=MilliSecs()
Color 255,255,255
Text 0,0,tt-old_tt
Text 0,16,do_gloom
Flip 0
Wend
End
Function quick_blur(w,h,passes=1,buffer=0)
If passes<1 Then passes=1
passes=passes-1
If buffer=0 Then buffer = BackBuffer()
SetBuffer Buffer
LockBuffer(Buffer)
For j=0 To h-1
For i=0 To w-1
proc_array(i,j)=ReadPixelFast(i,j) ;And $FFFFFF
Next
Next
For dbass=0 To passes
For j=0 To h-1
For i=1 To w-1
proc_array(i,j)=((proc_array(i,j)And $FEFEFF)Shr 1)+((proc_array(i-1,j)And $FEFEFF)Shr 1)
Next
For i=w-2 To 0 Step -1
proc_array(i,j)=((proc_array(i,j)And $FEFEFE)Shr 1)+((proc_array(i+1,j)And $FEFEFE)Shr 1)
Next
Next
For i=0 To w-1
For j=1 To h-1
proc_array(i,j)=((proc_array(i,j)And $FEFEFF)Shr 1)+((proc_array(i,j-1)And $FEFEFF)Shr 1)
Next
For j=h-2 To 0 Step -1
proc_array(i,j)=((proc_array(i,j)And $FEFEFE)Shr 1)+((proc_array(i,j+1)And $FEFEFE)Shr 1)
Next
Next
Next
For j=0 To h-1
For i=0 To w-1
WritePixelFast i,j,proc_array(i,j)
Next
Next
UnlockBuffer(Buffer)
End Function
Function CreateQuad(parent=0)
; creates a quad, facing to the right side
mesh=CreateMesh(parent)
surf=CreateSurface(mesh)
v0=AddVertex(surf, -1.0, 1.0,0, 0,0 )
v1=AddVertex(surf, 1.0, 1.0,0, 1,0 )
v2=AddVertex(surf, 1.0, -1.0,0, 1,1 )
v3=AddVertex(surf, -1.0, -1.0,0, 0,1 )
AddTriangle(surf,v0,v1,v2)
AddTriangle(surf,v0,v2,v3)
UpdateNormals mesh
Return mesh
End Function
You might think there is no reason to copy the backbuffer to an magebuffer, then scale the backbuffer, then restore it from the imagebuffer, instead of simply scaling the imagebuffer instead.
The reason why is, for some reason, doing the scaling in the backbuffer is much faster than in the imagebuffer. Even with the additional restoring of the full backbuffer it's still faster.
So how could I make this faster? Please note, using a smaller Screen resolution or gloom texture is no option. Also, when using only one blur pass instead of 2, you will see the flicker effect I mentioned.