Code archives/3D Graphics - Misc/Distant Object Renderer
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| This code may be useful for some people if they want to render feild of view type effects, but it won't speed up rendering anything in the distance. There is a speed cost associated with the effect, but it's not too bad. | |||||
; This is the location in the world where the blur camera will reside.
; This location should be far from any other geometry you have in your world.
Const DOA_BLUR_CAM_X# = 65536.0
Const DOA_BLUR_CAM_Y# = 65536.0
Const DOA_BLUR_CAM_Z# = 0.0
Const RENDER_DISTANCE_EPSILON# = 256
; Distant Object Accelerator
Type DOA_Camera
Field Camera ; This is the camera which this DOA_Camera should augment. If you have only one camera in your game, then set this to point to it.
Field Camera_Zoom# ; These are the values set for the above camera. They need to match it so that the augmented view matches the real view.
Field Camera_Range_Near#
Field Camera_Range_Far#
Field Camera_FogMode
Field Camera_FogRange_Near#
Field Camera_FogRange_Far#
Field Camera_FogColor_R
Field Camera_FogColor_G
Field Camera_FogColor_B
Field Resolution ; This is the resolution to render the augmented view's images at. This must be a power of 2 in size. The smaller this value the blurrier the objects in the distance will be.
Field Range_Far# ; This is the distance which the augmented view should render out to. This should be much greater than your main camera's far clipping plane.
Field Cube_Mesh
Field Cube_Map[6]
Field Cube_Brush[6]
Field Cube_Render_X# ; This is the location in the world at which the cube map was rendered. It is used to determine if the map needs to be re-rendered.
Field Cube_Render_Y#
Field Cube_Render_Z#
End Type
; -------------------------------------------------------------------------------------------------------------------
; You must create a DOA_Camera and set it's properties before calling this function.
; -------------------------------------------------------------------------------------------------------------------
Function DOA_InitCam(CAM_Create.DOA_Camera)
; Make sure we'll be able to render the textures when the time comes...
If GraphicsHeight() < CAM_Create\Resolution
RuntimeError("Video mode not tall enough for this texture resolution!")
EndIf
; Create a mesh for this camera's skybox.
CAM_Create\Cube_Mesh = DOA_CreateSkyBox()
EntityFX CAM_Create\Cube_Mesh, 1+8+16
;ScaleEntity CAM_Create\Cube_Mesh, 100, 100, 100
; Render the skybox behind everything else.
EntityOrder CAM_Create\Cube_Mesh, 255
; Loop through each of the box's sides, create a brush+texture for it, and paint it.
For LOOP_Side = 0 To 5
CAM_Create\Cube_Brush[LOOP_Side] = CreateBrush()
CAM_Create\Cube_Map[LOOP_Side] = CreateTexture(CAM_Create\Resolution, CAM_Create\Resolution, 16+32+256)
BrushTexture CAM_Create\Cube_Brush[LOOP_Side], CAM_Create\Cube_Map[LOOP_Side]
PaintSurface GetSurface(CAM_Create\Cube_Mesh, LOOP_Side+1), CAM_Create\Cube_Brush[LOOP_Side]
Next
End Function
; -------------------------------------------------------------------------------------------------------------------
; -------------------------------------------------------------------------------------------------------------------
Function DOA_Render(CAM_Main.DOA_Camera, Force_Render=0)
; Hide the camera we're currently rendering with.
HideEntity CAM_Main\Camera
; Hide the skybox we're going to render to.
HideEntity CAM_Main\Cube_Mesh
; Store the location of the main camera.
CAM_Main_X# = EntityX#(CAM_Main\Camera, True)
CAM_Main_Y# = EntityY#(CAM_Main\Camera, True)
CAM_Main_Z# = EntityZ#(CAM_Main\Camera, True)
; Create a new camera to render with.
CAM_Render = CreateCamera()
; Set the camera to clear the color and zbuffer.
CameraClsMode CAM_Render, True, True
; Set the camera view to a 90 degree fov, so that we can render the six views we need for a skybox.
DOA_SetCameraFOV(CAM_Render, 90)
; Set the camera's viewport to render the size of the texture requested.
CameraViewport CAM_Render, 0, 0, CAM_Main\Resolution, CAM_Main\Resolution
; Adjust the render camera's settings match the settings of the real camera.
CameraFogMode CAM_Render, CAM_Main\Camera_FogMode
CameraFogRange CAM_Render, CAM_Main\Camera_FogRange_Near#, CAM_Main\Camera_FogRange_Far#
CameraFogColor CAM_Render, CAM_Main\Camera_FogColor_R, CAM_Main\Camera_FogColor_G, CAM_Main\Camera_FogColor_B
; Set the render camera to render starting from the real camera's far clipping plane (minus some fraction of the
; range to keep holes from appearing in the map, and render out to the specified range.
CameraRange CAM_Render, CAM_Main\Camera_Range_Far#-(CAM_Main\Camera_Range_Far#/1.5), CAM_Main\Range_Far#
; Position the camera at the same location as the real camera.
PositionEntity CAM_Render, CAM_Main_X#, CAM_Main_Y#, CAM_Main_Z#
; Position the skybox at the same location as the real camera.
PositionEntity CAM_Main\Cube_Mesh, CAM_Main_X#, CAM_Main_Y#, CAM_Main_Z#
; Determine the distance of the main camera from the last location at which we rendered the scene.
Difference# = Sqr((CAM_Main_X#-CAM_Main\Cube_Render_X#)^2.0 + (CAM_Main_Y#-CAM_Main\Cube_Render_Y#)^2.0 + (CAM_Main_Z#-CAM_Main\Cube_Render_Z#)^2.0)
; If the skybox is out of date, rerender it.
If Difference# >= RENDER_DISTANCE_EPSILON#
;AntiAlias True
; Store the location in the world at which this cube map was rendered.
CAM_Main\Cube_Render_X# = CAM_Main_X#
CAM_Main\Cube_Render_Y# = CAM_Main_Y#
CAM_Main\Cube_Render_Z# = CAM_Main_Z#
;For LOOP_Side = 0 To 5
For LOOP_Side = 0 To 0
Select LOOP_Side
Case 0 ; North
RotateEntity CAM_Render, 0, 0, 0
Case 1 ; East
RotateEntity CAM_Render, 0, -90, 0
Case 2 ; South
RotateEntity CAM_Render, 0, 180, 0
Case 3 ; West
RotateEntity CAM_Render, 0, 90, 0
Case 4 ; Up
RotateEntity CAM_Render, -90, 0, 0
Case 5 ; Down
RotateEntity CAM_Render, 90, 0, 0
End Select
; Render the view.
RenderWorld
; Copy the view to the texture.
CopyRect 0, 0, CAM_Main\Resolution, CAM_Main\Resolution, 0, 0, BackBuffer(), TextureBuffer(CAM_Main\Cube_Map[LOOP_Side])
; Blur the texture.
;HideEntity CAM_Render
;DOA_BlurTexture2(CAM_Main\Cube_Map[LOOP_Side], 1, 1.0)
;ShowEntity CAM_Render
; Reset the texture's blending mode, scale, and position, because DOA_BlurTexture modifies them.
;TextureBlend CAM_Main\Cube_Map[LOOP_Side], 2
;ScaleTexture CAM_Main\Cube_Map[LOOP_Side], 1, 1
;PositionTexture CAM_Main\Cube_Map[LOOP_Side], 0, 0
;AntiAlias False
Next
EndIf
; Show the skybox we just rendered to.
ShowEntity CAM_Main\Cube_Mesh
; Delete the render camera.
FreeEntity CAM_Render
; Show the main camera again.
ShowEntity CAM_Main\Camera
End Function
; -------------------------------------------------------------------------------------------------------------------
; -------------------------------------------------------------------------------------------------------------------
Function DOA_CreateSkyBox()
Sky = CreateMesh()
; North
SURF_Sky = CreateSurface(Sky)
AddVertex SURF_Sky,+1,+1,+1,1,0
AddVertex SURF_Sky,-1,+1,+1,0,0
AddVertex SURF_Sky,-1,-1,+1,0,1
AddVertex SURF_Sky,+1,-1,+1,1,1
AddTriangle SURF_Sky,0,1,2
AddTriangle SURF_Sky,0,2,3
; East
SURF_Sky = CreateSurface(Sky)
AddVertex SURF_Sky,+1,+1,-1,1,0
AddVertex SURF_Sky,+1,+1,+1,0,0
AddVertex SURF_Sky,+1,-1,+1,0,1
AddVertex SURF_Sky,+1,-1,-1,1,1
AddTriangle SURF_Sky,0,1,2
AddTriangle SURF_Sky,0,2,3
; South
SURF_Sky = CreateSurface(Sky)
AddVertex SURF_Sky,-1,+1,-1,1,0
AddVertex SURF_Sky,+1,+1,-1,0,0
AddVertex SURF_Sky,+1,-1,-1,0,1
AddVertex SURF_Sky,-1,-1,-1,1,1
AddTriangle SURF_Sky,0,1,2
AddTriangle SURF_Sky,0,2,3
; West
SURF_Sky = CreateSurface(Sky)
AddVertex SURF_Sky,-1,+1,+1,1,0
AddVertex SURF_Sky,-1,+1,-1,0,0
AddVertex SURF_Sky,-1,-1,-1,0,1
AddVertex SURF_Sky,-1,-1,+1,1,1
AddTriangle SURF_Sky,0,1,2
AddTriangle SURF_Sky,0,2,3
; Top
SURF_Sky = CreateSurface(Sky)
AddVertex SURF_Sky,-1,+1,+1,1,1
AddVertex SURF_Sky,+1,+1,+1,1,0
AddVertex SURF_Sky,+1,+1,-1,0,0
AddVertex SURF_Sky,-1,+1,-1,0,1
AddTriangle SURF_Sky,0,1,2
AddTriangle SURF_Sky,0,2,3
; Bottom
SURF_Sky = CreateSurface(Sky)
AddVertex SURF_Sky,-1,-1,-1,0,1
AddVertex SURF_Sky,+1,-1,-1,0,0
AddVertex SURF_Sky,+1,-1,+1,1,0
AddVertex SURF_Sky,-1,-1,+1,1,1
AddTriangle SURF_Sky,0,1,2
AddTriangle SURF_Sky,0,2,3
;FlipMesh Sky
Return Sky
End Function
; -------------------------------------------------------------------------------------------------------------------
; This function sets the camera's horizontal FOV, in degrees.
; -------------------------------------------------------------------------------------------------------------------
Function DOA_SetCameraFOV(Camera, FOV#)
CameraZoom Camera, 1.0 / Tan(FOV#/2.0)
End Function
; -------------------------------------------------------------------------------------------------------------------
; This function blurs a texture using a technique that takes advantage of 3D acceleration.
;
; * You MUST hide all other cameras before calling this function!
; * You MUST reset your texture's blending mode, scale, and position after calling this function!
;
; Texture is the texture you want blurred.
;
; Blur_Quality defines the quality of the blur. 1 = 4 passes, 2 = 8 passes, 3 = 12 passes, etc.
;
; (The reason that the passes are in multiples of four is because interference artifacts are created when
; the number of passes is not a multiple of four... meaning that ten passes will actually look far worse
; than eight.)
;
; Blur_Radius# defines the radius of the blur, in pixels, assuming a map size of 256x256.
;
; (Ie, a radius of 16 will be the same width regardless of whether the texture is 16x16 or 512x512. It will
; only be exactly 16 pixels wide if the map is 256x256.)
; -------------------------------------------------------------------------------------------------------------------
Function DOA_BlurTexture(Texture, Blur_Quality, Blur_Radius#)
; This is used for temporary storage of the meshes used for soft shadow blurring.
Local BlurMesh[16*4]
; If blurring is enabled...
If Blur_Quality > 0
Blur_Cam = CreateCamera()
; Set the camera's range to be very small so as to reduce the possiblity of extra objects making it into the scene.
CameraRange Blur_Cam, 0.1, 100
; Set the camera to zoom in on the object to reduce perspective error from the object being too close to the camera.
CameraZoom Blur_Cam, 16.0
; Aim camera straight down.
RotateEntity Blur_Cam, 90, 0, 0, True
; Set the camera viewport to the same size as the texture.
CameraViewport Blur_Cam, 0, 0, TextureWidth(Texture), TextureHeight(Texture)
; Set the camera so it clears the color buffer before rendering the texture.
CameraClsColor Blur_Cam, 0,0,0
CameraClsMode Blur_Cam, True, True
; Position the blur camera far from other entities in the world.
PositionEntity Blur_Cam, DOA_BLUR_CAM_X#, DOA_BLUR_CAM_Y#, DOA_BLUR_CAM_Z#
; Create the sprites to use for blurring the shadow maps.
For Loop = 0 To (Blur_Quality*4)-1
BlurMesh[Loop] = CreateSprite()
Next
; Set the caster texture to multiply blend mode so we can darken it by changing the entity
; color when blurring.
TextureBlend Texture, 2
; Scale the texture down because we scale the sprites up so they fill a larger area of the
; screen. (Otherwise the edges of the texture are darker than the middle because they don't
; get covered.
ScaleTexture Texture, 0.5, 0.5
PositionTexture Texture, 0.5, 0.5
; Blur texture by blitting semi-transparent copies of it on top of it.
BlurRadius# = Blur_Radius# * (1.0 / 256.0)
BlurAngleStep# = 360.0 / Float(Blur_Quality*4)
; Normally we would just divide 255 by the number of passes so that adding all the passes
; together would not exceed 256. However, if we did that, then we could not have a number of
; passes which does not divide 256 evenly, or else the error would result in the white part of
; the image being slightly less than white. So we round partial values up to ensure that
; white will always be white, even if it ends up being a little whiter than white as a result
; when all the colors are added, since going higher than white just clamps to white.
BlurShade = Ceil(255.0 / Float(Blur_Quality*4))
; Place each of the blur objects around a circle of radius blur_radius.
For Loop = 0 To (Blur_Quality*4)-1
EntityTexture BlurMesh[Loop], Texture
EntityFX BlurMesh[Loop], 1+8
EntityBlend BlurMesh[Loop], 3
EntityColor BlurMesh[Loop], BlurShade, BlurShade, BlurShade
ScaleSprite BlurMesh[Loop], 2, 2
BlurAngle# = BlurAngleStep# * Float(Loop) + 180.0*(Loop Mod 2)
Xoff# = BlurRadius# * Cos(BlurAngle#)
Yoff# = BlurRadius# * Sin(BlurAngle#)
PositionEntity BlurMesh[Loop], DOA_BLUR_CAM_X# + Xoff#, DOA_BLUR_CAM_Y# - 16.0, DOA_BLUR_CAM_Z# + Yoff#, True
Next
; Render the new texture.
RenderWorld
; Copy the new texture from the screen buffer to the texture buffer.
CopyRect 0, 0, TextureWidth(Texture), TextureHeight(Texture), 0, 0, BackBuffer(), TextureBuffer(Texture)
; Free the blur entities.
For Loop = 0 To (Blur_Quality*4)-1
FreeEntity BlurMesh[Loop]
Next
; Free the blur camera.
FreeEntity Blur_Cam
EndIf
End Function
; -------------------------------------------------------------------------------------------------------------------
; This function blurs a texture using a technique that takes advantage of 3D acceleration.
;
; * You MUST hide all other cameras before calling this function!
; * You MUST reset your texture's blending mode, scale, and position after calling this function!
;
; Texture is the texture you want blurred.
;
; Blur_Quality defines the quality of the blur. 1 = 4 passes, 2 = 8 passes, 3 = 12 passes, etc.
;
; (The reason that the passes are in multiples of four is because interference artifacts are created when
; the number of passes is not a multiple of four... meaning that ten passes will actually look far worse
; than eight.)
;
; Blur_Radius# defines the radius of the blur, in pixels, assuming a map size of 256x256.
;
; (Ie, a radius of 16 will be the same width regardless of whether the texture is 16x16 or 512x512. It will
; only be exactly 16 pixels wide if the map is 256x256.)
; -------------------------------------------------------------------------------------------------------------------
Function DOA_BlurTexture2(Texture, Blur_Quality, Blur_Radius#)
; This is used for temporary storage of the meshes used for soft shadow blurring.
Local BlurMesh[16*4]
; If blurring is enabled...
If Blur_Quality > 0
Blur_Cam = CreateCamera()
; Set the camera's range to be very small so as to reduce the possiblity of extra objects making it into the scene.
CameraRange Blur_Cam, 0.1, 100
; Set the camera to zoom in on the object to reduce perspective error from the object being too close to the camera.
CameraZoom Blur_Cam, 16.0
; Aim camera straight down.
RotateEntity Blur_Cam, 90, 0, 0, True
; Set the camera viewport to the same size as the texture.
CameraViewport Blur_Cam, 0, 0, TextureWidth(Texture), TextureHeight(Texture)
; Set the camera so it clears the color buffer before rendering the texture.
CameraClsColor Blur_Cam, 0,0,0
CameraClsMode Blur_Cam, True, True
; Position the blur camera far from other entities in the world.
PositionEntity Blur_Cam, DOA_BLUR_CAM_X#, DOA_BLUR_CAM_Y#, DOA_BLUR_CAM_Z#
; Create the sprites to use for blurring the shadow maps.
For Loop = 0 To (Blur_Quality*4)-1
BlurMesh[Loop] = CreateSprite()
Next
; Scale the texture down because we scale the sprites up so they fill a larger area of the
; screen. (Otherwise the edges of the texture are darker than the middle because they don't
; get covered.
ScaleTexture Texture, 0.5, 0.5
PositionTexture Texture, 0.5, 0.5
; Blur texture by blitting semi-transparent copies of it on top of it.
BlurRadius# = Blur_Radius# * (1.0 / 256.0)
BlurAngleStep# = 360.0 / Float(Blur_Quality*4)
; Normally we would just divide 255 by the number of passes so that adding all the passes
; together would not exceed 256. However, if we did that, then we could not have a number of
; passes which does not divide 256 evenly, or else the error would result in the white part of
; the image being slightly less than white. So we round partial values up to ensure that
; white will always be white, even if it ends up being a little whiter than white as a result
; when all the colors are added, since going higher than white just clamps to white.
BlurShade = Ceil(255.0 / Float(Blur_Quality*4))
; Place each of the blur objects around a circle of radius blur_radius.
For Loop = 0 To (Blur_Quality*4)-1
EntityTexture BlurMesh[Loop], Texture
EntityFX BlurMesh[Loop], 1+8
EntityAlpha BlurMesh[Loop], 1.0 / Float(Loop+1)
ScaleSprite BlurMesh[Loop], 2, 2
BlurAngle# = BlurAngleStep# * Float(Loop) + 180.0*(Loop Mod 2)
Xoff# = BlurRadius# * Cos(BlurAngle#)
Yoff# = BlurRadius# * Sin(BlurAngle#)
PositionEntity BlurMesh[Loop], DOA_BLUR_CAM_X# + Xoff#, DOA_BLUR_CAM_Y# - 16.0, DOA_BLUR_CAM_Z# + Yoff#, True
Next
; Render the new texture.
RenderWorld
; Copy the new texture from the screen buffer to the texture buffer.
CopyRect 0, 0, TextureWidth(Texture), TextureHeight(Texture), 0, 0, BackBuffer(), TextureBuffer(Texture)
; Free the blur entities.
For Loop = 0 To (Blur_Quality*4)-1
FreeEntity BlurMesh[Loop]
Next
; Free the blur camera.
FreeEntity Blur_Cam
EndIf
End Function |
Comments
None.
Code Archives Forum