best way to shadowmap a terrain with objects
Blitz3D Forums/Blitz3D Programming/best way to shadowmap a terrain with objects
| ||
I have a blitz terrain with mulitiple objects (trees, architecture, etc). My terrain is already shadowmapped so I just need the objects shadowmapped to the terrain. At the moment I'm using the old copy/rotate/snapshot method that shadowmaps everything during game launch and then I run swift's old texture blur routine. Anyone have a better method for this? |
| ||
I have a similar problem although I'm using vertex lighting on static scene elements in stead of shadowmaps, but the problem is the same - if you got a brightly lit object lying in a dark corner, that will look rubbish. I haven't tested this (but should work I think) is to use EntityColor() on the dynamic objects. Coloring it black will make it black (ie max darkness) and coloring it white will show it in full brightness. You then have to manually do a raytrace (linepick) to the light sources to determin the exact amount of light (in the range from black to white) the dynamic objects should get. This will 'darken' en 'lighten' them in real time. The tricky side is that this will require a linepick (expensive function) and probably a distance check as well (meaning you need a SQR = also expensive function) in order to define the fall off for each light. So a routine that handles this must be load-balanced in order not to leach too many milliseconds per frame or it will clog up your performance... In my case I'm using ODE physics on my dynamic objects, so I can check if they are 'moving' or not. And so, if they are moving they will get 'lit' by that routine. If they are not moving (just lying around somewhere) they are skipped and assumed they have been previously lit properly... hope this helps, Danny. |
| ||
Not totally sure if this is of any help to you, but here's some fuctions from my own (not completely finished, but this works) lighting routines... You can't run this code (without the 57 other include files :) but the code in the LIGHT_GetLightAtPosition function might help you out or give you an idea?! It was originally written for vertex lighting (and is still used for it), but it basically calculates the amount of light a certain xyz point should receive - you can apply the resulting RGB value to a vertex or EntityColor as you wish...Global LIGHT_VALUE[2] ; RGB storage container for Vertex Lighting routines Const LIGHT_RET_BUSY = 0 ; lighting routine has NOT FINISHED lighting the entire entity YET. Const LIGHT_RET_DONE = 1 ; lighting routine HAS FINISHED lighting the entity, and ready for the next one. ;Light shapes Const LIGHT_SHAPE_DIRECTIONAL = 1 Const LIGHT_SHAPE_POINTLIGHT = 2 Const LIGHT_SHAPE_SPOTLIGHT = 3 Const LIGHT_SHAPE_LINEAR = 4 ; Note: VERTEX light only! Const LIGHT_SHAPE_AREA = 5 ; Note: VERTEX light only! Const LIGHT_SHAPE_ENTITY = 6 ; Note: VERTEX light only! ;Light types Const LIGHT_TYPE_VERTEX = 0 ; pre-calculated vertex light Const LIGHT_TYPE_DX7 = 1 ; live DirectX7 light (note: max 7 or 8!) Type node_light Field entity.node_entity ; handle back to entity (to quickly parse through lights!) Field lightShape ; light type (0=ambient, 1=direction, 2=point, 3=spot) Field lightType ; see LIGHT_TYPE_ consts Field red, green, blue ; light color (seriously!) Field intensity# ; value between typically between -1.0 and 1.0 (-1 = negative light) Field doFallOff ; toggle Field FallOffNear#,FallOffFar# ; intensity falloff (all light types) Field innerAngle#, outerAngle# ; for spotlights Field ShadowCaster ; true is this lamp casts shadows Field shbrightness# ; shadow brightness (0=black, 1=full shadow color) Field shRed, ShGreen, shBlue ; shadow color Field prjMapFilename$ ;* ; RESERVED BUT NOT USED YET! - filename of projection map/texture ;live entity handles Field prjMapHandle ; IMAGE handle to projection map Field light ; blitz entity handle End Type Function LIGHT_RenderEntityColor( ent.node_entity ) ;| Lights the entity by setting it's entity color to make it dark or full bright. ;| ;| Used on DYNAMIC entities. ;Set shading FX on entity (for Entity Coloring) EntityFX ent\model\mesh, 1+ent\model\refModel\Fx ;prevent picking itself ENT_setPickMode ent, 0, False ;calc light LIGHT_GetLightAtPosition ent, EntityX#(ent\master,1), EntityY#(ent\master,1), EntityZ#(ent\master,1) ;set entity color EntityColor ent\model\mesh, LIGHT_VALUE[0],LIGHT_VALUE[1],LIGHT_VALUE[2] ;restore pickmode ENT_setPickMode ent, 2, True Return LIGHT_RET_DONE End Function Function LIGHT_GetLightAtPosition( ent.node_entity, vx#,vy#,vz# ) ;| NOTE: Assumes the entity has been tested to have a MODEL NODE! ;| NOTE: Uses the LIGHT_VALUE[3] global array for returning final RGB values for given coordinates ;reset vertex color LIGHT_VALUE[0] = 0 ;Red channel LIGHT_VALUE[1] = 0 ;Green channel LIGHT_VALUE[2] = 0 ;Blue channel ;check if entity receives shadow doShadow = ent\model\refmodel\ShadowReceive ;now parse EVERY LIGHT For light.node_light = Each node_light If (light\entity\enabled) And (light\lightType = LIGHT_TYPE_VERTEX) Then ;get light data lx# = EntityX#(light\light,1) ly# = EntityY#(light\light,1) lz# = EntityZ#(light\light,1) lR=0 : lG=0 : lB=0 ;act pending shape of vertex light Select light\lightShape Case LIGHT_SHAPE_POINTLIGHT DoFade = False ; fade between COLOR and SHADOW colors within Fallof range! ;get lamp-vertex vector dx# = vx-lx dy# = vy-ly dz# = vz-lz ;check for FALLOFF If light\doFallOff Then ;get distance dist# = Sqr(dx*dx + dy*dy + dz*dz) ;check range If dist# <= light\falloffNear# Then mult# = 1.0 ElseIf dist# <= light\falloffFar# ;calc falloff mult# = 1.0-(dist#-light\falloffNear#) / (light\fallofffar#-light\falloffNear#) doFade = True Else ;out of range mult = 0 EndIf Else ;no fallof, so always color shadow (if any detected next) mult# = 1.0 EndIf ;check for shadowcasting If doShadow Then If (light\shadowCaster=True) And (mult > 0) Then ;ray pickMesh = LinePick(lx#,ly#,lz#, dx#,dy#,dz#) If pickMesh <> 0 Then ;RAY hit Something - get distance between vertex & picked point pvx# = PickedX#()-vx# pvy# = PickedY#()-vy# pvz# = PickedZ#()-vz# pdist# = Sqr( pvx*pvx + pvy*pvy + pvz*pvz ) ;when ray stopped SHORT, it must be blocked: SHADOW If pdist# > 0.01 Then mult# = mult# * light\shBrightness# doFade = True ; COLOR SHADOW! EndIf Else ;Ray Stopped short or overshot, but didn't hit anything! ;do nothing to keep current mult! EndIf EndIf EndIf If doFade Then ;Mix between light & shadow color LR = Interpolate_Linear1D((light\red * light\intensity#), light\shRed , 1-mult#) LG = Interpolate_Linear1D((light\green * light\intensity#), light\shGreen , 1-mult#) LB = Interpolate_Linear1D((light\blue * light\intensity#), light\shBlue , 1-mult#) Else ;Mix between light & shadow color LR = Interpolate_Linear1D((light\red * light\intensity#), light\shRed * mult# , 1-mult#) LG = Interpolate_Linear1D((light\green * light\intensity#), light\shGreen * mult#, 1-mult#) LB = Interpolate_Linear1D((light\blue * light\intensity#), light\shBlue * mult# , 1-mult#) EndIf Default ;unsupported / unkown light shape End Select ;ADD LIGHT result to VERTEX color LIGHT_VALUE[0] = LIGHT_VALUE[0] + lR LIGHT_VALUE[1] = LIGHT_VALUE[1] + lG LIGHT_VALUE[2] = LIGHT_VALUE[2] + lB EndIf Next ;check the GLOBAL LIGHT_VALUE[RGB] for results! ; ------ End Function Function Interpolate_Linear1D#( A#, B#, tween# ) Return ((1.0-tween#) * A#) + (tween# * B#) End Function Danny |