Code archives/3D Graphics - Effects/Cube mapping made 6x faster and easier
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
May 03 2005; MultiTexturing problem spotted by SnarkBait fixed. ----------------------------------------------------------- Okay, today, i decided to look at cubemapping- something ive not played with before. I got the demo from blitz to work, and fixed a couple of its bugs (not hiding the camera) so some of the credit goes to the author of that demo. This system allows you to turn any loaded mesh into a "cubemapped" mesh- by calling one command. the system keeps track of cameras and textures on its own. Usage: To make an object cubemapped: addcubemapobject(mesh,texturesize,texturelayer) turns "mesh" into a cubemapped entity Updatecubemaps() Goes through all cubemap objects and updates their textures Deletecubemapobject(mesh) Deletes the cubemap resources from "mesh" Deleteallcubemapobjects() Frees all cubemapping resources All thats required to get this to work: Addcubemapobject(mesh,256) and updatecubemaps() [edit] Just added a new command: cubemeshCameraRange(mesh,CameraRangemin#,CameraRangemax#) This sets how far the camera that renderes the reflection can "see" :D [New version] Okay, so i didnt need several cameras for several objects, so i overhauled the camera management... The usage is exactly the same as before, except if you change graphics modes without clearing all the objects, youl get a Memory Access Violation. Make sure you use Deleteallcubemapobjects() before changing graphics mode :) New commands on 03/10/04: BIG UPDATE! Setcubemapupdatefrequency (okay so this may need changing) Setcubemapupdatefrequency(mesh,frames,faceperrender) Sets how many "updatecubemaps" should be executed before this cubemapped entity gets cubemapped. If faceperrender=1 then it only updates 1 face of each cubemap every update, which is efficient but can cause glitches depending on the scenery. this means much faster "realtime" cubemapping though! UpdateNextCubemap() ;Iterates to the next cubemap and updates it. call this instead of updatecubemaps each frame for a higher framerate. this command disregards the above commands "frames" property.. | |||||
Global scx=640,scy=480 Graphics3D scx,scy,16,2 light=CreateLight() plane=CreatePlane() gld=CreateTexture(255,255) SetBuffer TextureBuffer(gld) For x=0 To 128 Color x,x*2,x*3 Rect x,x,255-x/2,255-x/2,0 Next SetBuffer BackBuffer() ScaleTexture gld,100,100 EntityTexture plane,gld camera=CreateCamera() CameraClsColor camera,10,20,250 Pivot=CreatePivot() EntityParent camera,Pivot PositionEntity camera,0,20,-30 ;Create some entities to cubemap sphere=CreateSphere(20) PositionEntity sphere,0,20,10 ScaleEntity sphere,10,10,10 cube=CreateCube() PositionEntity cube,0,20,-10 ScaleEntity cube,5,5,5 ;Cubemap them! addcubemapobject(cube,256,0) addcubemapobject(sphere,128,0) ;You dont need to do the next couple of lines, but its good for efficiency: setcubemapupdatefrequency(cube,2,1) ;Update cube every 15 frames, and enable "face per render" (update only a part of the cubemap every update) setcubemapupdatefrequency(sphere,2,1) ;Update sphere every 15 frames, and enable "face per render" (update only a part of the cubemap every update) ;change the camera range of these two to speed things up cubemeshCameraRange(cube,10,250) cubemeshCameraRange(sphere,10,250) ;do a render loop Repeat mlt#=1 If KeyDown(57) Then mlt#=10 TurnEntity Pivot,0,.1*mlt#,0 TurnEntity cube,.1*mlt#,0,0 updatecubemaps() ;Update all cubemaps! ;or you can use : updatenextcubemap() ;Update NEXT cubemap! RenderWorld Flip Until KeyDown(1) Deletecubemapobject(cube) ;Delete the cubemap stuff from "cube" Deletecubemapobject(sphere) ;Delete the cubemap stuff from "sphere" Deleteallcubemapobjects() ;Alternatively, call this at the end to wipe all cubemap stuff End ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Cubemap System;;;;;;;;;;;;;;;;;;;;;;;;;;;; Type cubemapobject Field entity Field Texture Field detail Field cammin#,cammax# Field Lastupdate,updatefrequency Field Lastcamupdate Field faceperrender Field Lastface=1 End Type Global cubemapcameraent=0 Global Lastcubemapcount,cubemapcount Function clearcubemapsystem() Deleteallcubemapobjects() If cubemapcameraent<>0 Then FreeEntity cubemapcameraent:cubemapcameraent=0 End Function Function addcubemapobject(mesh,detail,Texturelayer=0,blendmode=2) Local t.cubemapobject=New cubemapobject t\entity=mesh Tx=CreateTexture(detail,detail,1+128+256) EntityTexture mesh,tx,0,Texturelayer TextureBlend tx,blendmode t\Texture=tx t\detail=detail If cubemapcameraent=0 Then cubemapcameraent=CreateCamera():CameraProjMode cubemapcameraent,0 t\updatefrequency=1 t\Lastupdate=Lastcubemapcount CameraProjMode cubemapcameraent,0 t\cammin=1 t\cammax=1000 CameraRange cubemapcameraent,t\cammin,t\cammax updatecubemap(t\Texture,cubemapcameraent,t\entity) Lastcubemapcount=Lastcubemapcount+1;MilliSecs() End Function Function cubemeshCameraRange(mesh,CameraRangemin#,CameraRangemax#) ;sets how a cubemaped texture is rendered. Local n.cubemapobject For n=Each cubemapobject If n\entity=mesh Then n\cammin=CameraRangemin n\cammax=CameraRangemax EndIf Next End Function Function Deleteallcubemapobjects() Local n.cubemapobject For n=Each cubemapobject Deletecubemapobject n\entity Next If cubemapcameraent<>0 Then FreeEntity cubemapcameraent:cubemapcameraent=0 End Function Function Deletecubemapobject(mesh) Local n.cubemapobject For n=Each cubemapobject If n\entity=mesh Then If n\Texture<>0 Then FreeTexture n\Texture Delete n EndIf Next checkifanycubemapsleft() End Function Function checkifanycubemapsleft() Local cnt=0,n.cubemapobject For n=Each cubemapobject cnt=cnt+1 Next If cnt=0 Then clearcubemapsystem() End Function Function updatecubemaps() Local o.cubemapobject For o.cubemapobject=Each cubemapobject If (cubemapcount-o\Lastupdate)>o\updatefrequency Then CameraProjMode cubemapcameraent,0 CameraRange cubemapcameraent,o\cammin,o\cammax updatecubemap(o\Texture,cubemapcameraent,o\entity,o\Lastface*o\faceperrender):o\Lastface=(o\Lastface Mod 6)+1 o\Lastupdate=cubemapcount EndIf Next cubemapcount=cubemapcount+1 End Function Function updatenextcubemap() Local o.cubemapobject Local cnt=0,cnt2=0 For o.cubemapobject=Each cubemapobject cnt2=cnt2+1 Next For o.cubemapobject=Each cubemapobject cnt=cnt+1 If cubemapcount Mod (cnt2+1)=cnt Then;If (cubemapcount-o\Lastupdate)>o\updatefrequency Then CameraProjMode cubemapcameraent,0 CameraRange cubemapcameraent,o\cammin,o\cammax updatecubemap(o\Texture,cubemapcameraent,o\entity,o\Lastface*o\faceperrender):o\Lastface=(o\Lastface Mod 6)+1 o\Lastupdate=cubemapcount EndIf Next cubemapcount=cubemapcount+1 End Function Function setcubemapupdatefrequency(mesh,updaterate,faceperrender=0) Local o.cubemapobject For o.cubemapobject=Each cubemapobject If o\entity=mesh Then o\updatefrequency=updaterate:o\faceperrender=faceperrender Next End Function Function UpdateCubemap(tex,camera,entity,side=0) ;the bit ripped from the Blitz demo tex_sz=TextureWidth(tex) ; Show the camera we have specifically created for updating the cubemap CameraProjMode camera,1 ; Hide entity that will have cubemap applied to it. This is so we can get cubemap from its position, without it blocking the view HideEntity entity ; Position camera where the entity is - this is where we will be rendering views from for cubemap PositionEntity camera,EntityX#(entity,1),EntityY#(entity,1),EntityZ#(entity,1) CameraClsMode camera,False,True ; Set the camera's viewport so it is the same size as our texture - so we can fit entire screen contents into texture CameraViewport camera,0,0,tex_sz,tex_sz ; Update cubemap If side=0 Or side=1 Then ; do left view SetCubeFace tex,0 RotateEntity camera,0,90,0 RenderWorld CopyRect 0,0,tex_sz,tex_sz,0,0,BackBuffer(),TextureBuffer(tex) EndIf If side=0 Or side=2 Then ; do forward view SetCubeFace tex,1 RotateEntity camera,0,0,0 RenderWorld CopyRect 0,0,tex_sz,tex_sz,0,0,BackBuffer(),TextureBuffer(tex) EndIf If side=0 Or side=3 Then ; do right view SetCubeFace tex,2 RotateEntity camera,0,-90,0 RenderWorld CopyRect 0,0,tex_sz,tex_sz,0,0,BackBuffer(),TextureBuffer(tex) EndIf If side=0 Or side=4 Then ; do backward view SetCubeFace tex,3 RotateEntity camera,0,180,0 RenderWorld CopyRect 0,0,tex_sz,tex_sz,0,0,BackBuffer(),TextureBuffer(tex) EndIf If side=0 Or side=5 Then ; do up view SetCubeFace tex,4 RotateEntity camera,-90,0,0 RenderWorld CopyRect 0,0,tex_sz,tex_sz,0,0,BackBuffer(),TextureBuffer(tex) EndIf If side=0 Or side=6 Then ; do down view SetCubeFace tex,5 RotateEntity camera,90,0,0 RenderWorld CopyRect 0,0,tex_sz,tex_sz,0,0,BackBuffer(),TextureBuffer(tex) EndIf ; Show entity again ShowEntity entity ; Hide the cubemap camera CameraProjMode camera,0 End Function ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
Comments
| ||
I get an Entity does not exist. Remove the # from cubemapcameraent# . |
| ||
Yeah, handy stuff, but like xml says, don't ever use floats for entity handles! (Or images, sounds, etc.) |
| ||
Forgot to post... i fixed the # which was there from an earlier typo. Also fixed a problem with parented meshes where the camera would always be put at 0,0,0. |
| ||
I had to fix this to get multitexturing to work: EntityTexture mesh,tx,0,Texturelayer <== added the '0' in the 'frame' spot, and added blendmode and textureblend to the function. Function addcubemapobject(mesh,detail,Texturelayer=0,blendmode=2) Local t.cubemapobject=New cubemapobject t\entity=mesh Tx=CreateTexture(detail,detail,1+128+256) EntityTexture mesh,tx,0,Texturelayer TextureBlend tx,blendmode t\Texture=tx t\detail=detail If cubemapcameraent=0 Then cubemapcameraent=CreateCamera():CameraProjMode cubemapcameraent,0 t\updatefrequency=1 t\Lastupdate=Lastcubemapcount CameraProjMode cubemapcameraent,0 t\cammin=1 t\cammax=1000 CameraRange cubemapcameraent,t\cammin,t\cammax updatecubemap(t\Texture,cubemapcameraent,t\entity) Lastcubemapcount=Lastcubemapcount+1;MilliSecs() End Function |
| ||
Cheers for that. I have not had an issue though i did occasionally momentarily see some wierd artifacts. Thats a silly mistake (number 2 I suppose!) I'll update the entry now. |
| ||
awesome, i almost feel the colthmetal cool my skin when i watch this demo. well done. |
| ||
Too tired to continue working on this, but maybe someone will find it useful! (much confusion, as minib3d does not have createplane function) Blitzmax superstrict (currently not working) |
| ||
Very good procedure, add all for my code ;) |
Code Archives Forum