Ich versuche grade sowas ähnliches wie Sprite Lamp
in GLBasic hinzubekommen.
Leider bekomme ich bei den Höhenwerten hLU , hRU , hLD , hRD in
der Funktion drawLitSprite immer Null heraus, sodass ich nichtmal anfangen kann überlegungen
bezüglich der X und Z Winkel anX und anZ in Relation zur Lichtquellen Position anzustellen.
CONSTANT LightsMax = 10
CONSTANT SpriteMax = 100
TYPE vRGB
r% ; g% ; b%
ENDTYPE
TYPE light
color AS vRGB
range% // range of light ( Radius! )
kind% // kind of light ( other light reduction kinds till the end of the light range
exist%
x%
y%
ENDTYPE
TYPE sprite
srcTex$
srcH$
srcS$
iD%
x% ; y%
ENDTYPE
GLOBAL LightMap[] AS vRGB
GLOBAL Ambient AS vRGB
GLOBAL Lights[] AS light
main()
FUNCTION newSprite AS sprite: any AS sprite , iDG , sT$ , sH$ , sS$ , x , y
any.srcTex$ = sT$ ; any.srcH$ = sH$ ; any.srcS$ = sS$ ; any.iD = iDG ; any.x = x ; any.y = y
ENDFUNCTION
FUNCTION main:
LOCAL width% , height% , white AS vRGB , blue AS vRGB , red AS vRGB , ball AS sprite
LOCAL mX% , mY% , b1% , b2%
width = 320 ; height = 240
Ambient.r = 40 ; Ambient.g = 40 ; Ambient.b = 40
white.r = 255 ; white.g = 255 ; white.b = 255
blue.r = 120 ; blue.g = 120 ; blue.b = 255
red.r = 60 ; red.g = 255 ; red.b = 60
newSprite( ball , 100 , "bBall.bmp" , "bBallH.bmp" , "bBallS.bmp" , 160 , 120 )
SETCURRENTDIR("Media/Sprites") // go to media files
DIM LightMap[width][height] ; DIM Lights[LightsMax]
Lights[0].exist = TRUE ; Lights[0].x = 160 ; Lights[0].y = 120 ; Lights[0].range = 250 ; Lights[0].color = red
// Lights[1].exist = TRUE ; Lights[1].x = 160 ; Lights[1].y = 120 ; Lights[1].range = 50 ; Lights[1].color = blue
// Lights[2].exist = TRUE ; Lights[2].x = 60 ; Lights[2].y = 60 ; Lights[2].range = 50 ; Lights[2].color = white
WHILE NOT KEY( 30 )
MOUSESTATE mX , mY , b1 , b2
Lights[0].x = mX ; Lights[0].y = mY
// updateLightMap( width , height , Ambient )
X_MAKE2D
// drawLightMap( width , height )
drawLitSprite( ball )
SHOWSCREEN
WEND
ENDFUNCTION
FUNCTION drawLitSprite: spr AS sprite
LOCAL w% , h% , w2% , h2% , tMap%[] , hMap%[] , x% , y%
LOCAL hLD# , hRD# , hLU# , hRU# , hU# , hD# , hL# , hR# , anX# , anZ#
LOCAL lAllow% , rAllow% , dAllow% , uAllow% , dist# , clr AS vRGB , ok%
ok = LOADSPRITEMEM( spr.srcTex$ , w2 , h2 , hMap[] )
IF NOT ok THEN RETURN FALSE
ok = LOADSPRITEMEM( spr.srcTex$ , w , h , tMap[] )
IF NOT ok THEN RETURN FALSE
IF w2 <> w OR h2 <> h THEN RETURN FALSE // hMap has to be the same size as the texture size for this to work...
clr.r = Ambient.r ; clr.g = Ambient.g ; clr.b = Ambient.b
FOR i = 0 TO BOUNDS( hMap[] , 0 ) - 1
x = MOD( i , w ) ; y = i / w ;
IF bAND(ASR( hMap[ i ],24), 0xff) <> 0x00 // not pink "alpha" color...
hLD = ( bAND( hMap[ i ], 0x00ff00) / 255.0 ) * 100.0
hRD = ( bAND( hMap[ cB( ( x + 1 ) , 0 , ( w - 1 ) ) + ( y * w ) ] , 0xff ) / 255.0 ) * 100.0 // in debug I always get zero for those heights, also when I try to look at the value of hMap[ i ] I allways get the same value...
hLU = ( bAND( hMap[ x + ( cB( ( y + 1 ) , 0 , ( h - 1 ) ) * w ) ] , 0xff ) / 255.0 ) * 100.0
hRU = ( bAND( hMap[ cB( ( x + 1 ) , 0 , ( w - 1 ) ) + ( cB( ( y + 1 ) , 0 , ( h - 1 ) ) * w ) ] , 0xff ) / 255.0 ) * 100.0
hU = hLU + ( hRU - hLU ) / 2.0 ; hD = hLD + ( hRD - hLD ) / 2.0 ; hL = hLD + ( hLU - hLD ) / 2.0 ; hR = hRD + ( hRU - hRD ) / 2.0 // mean values
anZ = ATAN( ( hD - hU ) , 10.0 ) ; anX = ATAN( ( hL - hR ) , 10.0 ) // getting angles of steepness in right and up direction
lAllow = FALSE ; rAllow = FALSE ; dAllow = FALSE ; uAllow = FALSE
IF anX <= 0 THEN lAllow = TRUE ; IF anX >= 0 THEN rAllow = TRUE // light affecting this angle at all ?
IF anZ <= 0 THEN dAllow = TRUE ; IF anZ >= 0 THEN uAllow = TRUE // light affecting this angle at all ?
FOR i2 = 0 TO LightsMax - 1
IF Lights[i2].exist
IF ( Lights[i2].x > spr.x + x AND rAllow ) OR ( Lights[i2].x < spr.x + x AND lAllow ) OR ( Lights[i2].y > spr.y + y AND uAllow ) OR ( Lights[i2].y < spr.y + y AND dAllow ) // light affecting this angle at all ?
dist = SQR( POW( ( ( spr.x + x ) - Lights[i2].x ) , 2 ) + POW( ( ( spr.y + y ) - Lights[i2].y ) , 2 ) )
dist = Lights[i2].range - dist
IF dist > 0
dist = dist / ( Lights[i2].range / 2.0 )
dist = cBR( dist , 0 , 0.5 )
clr.r = clr.r + ( Lights[i2].color.r - clr.r ) *dist ; clr.g = clr.g + ( Lights[i2].color.g - clr.g ) * dist ; clr.b = clr.b + ( Lights[i2].color.b - clr.b ) * dist
ENDIF
ENDIF
ENDIF
NEXT
ENDIF
IF bAND(ASR(tMap[ i ],24), 0xff) <> 0x00
clr.r = clr.r - ( bAND( tMap[ i ], 0xff ) - clr.r ) / 2.0
clr.g = clr.g - ( bAND( ASR( tMap[ i ] , 8 ) , 0xff ) - clr.g ) / 2.0
clr.b = clr.b - ( bAND( ASR( tMap[ i ] , 16 ) , 0xff ) - clr.b ) / 2.0
SETPIXEL spr.x + x , spr.y + y , RGB( clr.r , clr.g , clr.b )
ENDIF
clr.r = Ambient.r ; clr.g = Ambient.g ; clr.b = Ambient.b
NEXT
DIM hMap[0] ; DIM tMap[0]
ENDFUNCTION
FUNCTION cB: value , minimum , maximum // in bounds checker
IF minimum > maximum THEN SWAP minimum , maximum
IF value < minimum THEN RETURN minimum
IF value > maximum THEN RETURN maximum
RETURN value
ENDFUNCTION
FUNCTION cBR#: value# , minimum# , maximum# // in bounds checker for floats
IF minimum > maximum THEN SWAP minimum , maximum
IF value < minimum THEN RETURN minimum
IF value > maximum THEN RETURN maximum
RETURN value#
ENDFUNCTION
Edit:
Habe grade gemerkt, dass ich die Quelldatei für die heightmap falsch angegeben hatte... :blink:
Kein Wunder dass da nix rauskam...
Mal schauen was daraus wird.
Habe es verbessert und schonmal grob den Effekt hinbekommen, den ich haben will.
Ich werde morgen versuchen den Effekt zu verfeinern,
werde anstatt die ungenaue Höhendifferenzbestimmung ( hDif# ) eine genaue höhenDifferenzbestimmung basierend auf Gleitkommawert koordinaten machen um den genauen Verlauf entlang der Richtung des Lichtstrahls zu bekommen.
// --------------------------------- //
// Project: 2DLight
// Start: Friday, January 02, 2015
// IDE Version: 12.312
CONSTANT LightsMax = 10
CONSTANT SpriteMax = 100
GLOBAL LightAngle#
TYPE vRGB
r% ; g% ; b%
ENDTYPE
TYPE light
color AS vRGB
range% // range of light ( Radius! )
kind% // kind of light ( other light reduction kinds till the end of the light range
exist%
x%
y%
ENDTYPE
TYPE sprite
srcTex$
srcH$
srcS$
iD%
x% ; y%
ENDTYPE
TYPE vec3D
x#
y#
z#
dX#
dY#
dZ#
ENDTYPE
GLOBAL LightMap[] AS vRGB
GLOBAL Ambient AS vRGB
GLOBAL Lights[] AS light
main()
FUNCTION dotP: vector1 AS vec3D , vector2 AS vec3D
RETURN vector1.dX * vector2.dX + vector1.dY * vector2.dY + vector1.dZ * vector2.dZ
ENDFUNCTION
FUNCTION magnitude: v AS vec3D
RETURN SQR( v.dX * v.dX + v.dY * v.dY + v.dZ * v.dZ )
ENDFUNCTION
FUNCTION newSprite AS sprite: s AS sprite , iDG , sT$ , sH$ , sS$ , x , y
s.srcTex$ = sT$ ; s.srcH$ = sH$ ; s.srcS$ = sS$ ; s.iD = iDG ; s.x = x ; s.y = y
ENDFUNCTION
FUNCTION newVector3D AS vec3D: v AS vec3D , x% , y% , z% , dX% , dY% , dZ%
v.x = x ; v.y = y ; v.z = z ; v.dX = dX ; v.dY = dY ; v.dZ = dZ
ENDFUNCTION
FUNCTION getAngleBetweenVec3D: v1 AS vec3D , v2 AS vec3D
RETURN dotP( v1 , v2 ) / ( magnitude( v1 ) * magnitude( v2 ) )
ENDFUNCTION
FUNCTION main:
LOCAL width% , height% , white AS vRGB , blue AS vRGB , red AS vRGB , ball AS sprite
LOCAL mX% , mY% , b1% , b2%
width = 320 ; height = 240
Ambient.r = 0 ; Ambient.g = 0 ; Ambient.b = 0
white.r = 255 ; white.g = 255 ; white.b = 255
blue.r = 120 ; blue.g = 120 ; blue.b = 255
red.r = 60 ; red.g = 255 ; red.b = 60
newSprite( ball , 100 , "bBall.bmp" , "bBallH.bmp" , "bBallS.bmp" , 160 , 120 )
SETCURRENTDIR("Media/Sprites") // go to media files
DIM LightMap[width][height] ; DIM Lights[LightsMax]
Lights[0].exist = TRUE ; Lights[0].x = 160 ; Lights[0].y = 120 ; Lights[0].range = 250 ; Lights[0].color = white
Lights[1].exist = TRUE ; Lights[1].x = 160 ; Lights[1].y = 120 ; Lights[1].range = 50 ; Lights[1].color = blue
Lights[2].exist = TRUE ; Lights[2].x = 60 ; Lights[2].y = 60 ; Lights[2].range = 50 ; Lights[2].color = white
WHILE NOT KEY( 30 )
MOUSESTATE mX , mY , b1 , b2
Lights[0].x = mX ; Lights[0].y = mY
updateLightMap( width , height , Ambient )
X_MAKE2D
drawLightMap( width , height )
drawLightSprite( ball )
PRINT LightAngle , 200 , 200
SHOWSCREEN
WEND
ENDFUNCTION
FUNCTION drawLightSprite: spr AS sprite
LOCAL w% , h% , w1% , h1% , w2% , h2% , tMap%[] , hMap%[] , x% , y% , value% , turn% , anIX# , anIZ# , hDif#
LOCAL hLD% , hRD% , hLU% , hRU% , ok% , anX# , anZ# , lDX# , lDY# , noEffect% , noXEffect% , noYEffect%
LOCAL hL# , hR# , hU# , hD#
LOCAL dist# , clr AS vRGB , v1 AS vec3D , v2 AS vec3D , vL AS vec3D
ok = LOADSPRITEMEM( spr.srcTex$ , w1 , h1 , tMap[] )
IF NOT ok THEN RETURN FALSE
ok = LOADSPRITEMEM( spr.srcH$ , w2 , h2 , hMap[] )
IF NOT ok THEN RETURN FALSE
IF w2 <> w1 OR h2 <> h1 THEN RETURN FALSE // hMap has to be the same size as the texture size for this to work...
w = w1 ; h = h1 ; clr.r = Ambient.r ; clr.g = Ambient.g ; clr.b = Ambient.b
LightAngle = ATAN( ( ( h / 2 ) + spr.y - Lights[0].y ) , ( ( w / 2.0 ) + spr.x - Lights[0].x ) )
FOR i = 0 TO BOUNDS( hMap[] , 0 ) - 1
x = MOD( i , w ) ; y = i / w ; value = hMap[ i ]
IF bAND(ASR(value,24), 0xff) <> 0x00 // not pink "alpha" color...
hLD = value
hRD = hMap[ cB( ( x + 1 ) , 0 , ( w - 1 ) ) + ( y * w ) ]
hLU = hMap[ x + ( cB( ( y + 1 ) , 0 , ( h - 1 ) ) * w ) ]
hRU = hMap[ cB( ( x + 1 ) , 0 , ( w - 1 ) ) + ( cB( ( y + 1 ) , 0 , ( h - 1 ) ) * w ) ]
IF hRD = 0xFFFF0080 THEN hRD = value ; IF hLU = 0xFFFF0080 THEN hLU = value ; IF hRU = 0xFFFF0080 THEN hRU = value // not pink "alpha" color...
hLD = bAND( hLD , 0xff ) ; hRD = bAND( hRD , 0xff ) ; hLU = bAND( hLU , 0xff ) ; hRU = bAND( hRU , 0xff )
hL = hLD + ( hLU - hLD ) / 2.0 ; hR = hRD + ( hRU - hRD ) / 2.0
hU = hLU + ( hRU - hLU ) / 2.0 ; hD = hLD + ( hRD - hLD ) / 2.0
FOR i2 = 0 TO LightsMax - 1
IF Lights[i2].exist
lDX = Lights[i2].x - ( spr.x + ( w / 2.0 ) ) ; lDY = Lights[i2].y - ( spr.y + ( h / 2.0 ) )
IF lDX = 0 AND lDY > 0 ; hDif = hD - hU ; ENDIF
IF lDX = 0 AND lDY < 0 ; hDif = hU - hD ; ENDIF
IF lDX > 0 AND lDY = 0 ; hDif = hL - hR ; ENDIF
IF lDX < 0 AND lDY = 0 ; hDif = hR - hL ; ENDIF
IF lDX > 0 AND lDY > 0 ; hDif = hLD - hRU ; ENDIF
IF lDX < 0 AND lDY > 0 ; hDif = hRD - hLU ; ENDIF
IF lDX > 0 AND lDY < 0 ; hDif = hLU - hRD ; ENDIF
IF lDX < 0 AND lDY < 0 ; hDif = hRU - hLD ; ENDIF
newVector3D( v1 , spr.x + x , hLD , spr.y + y , lDX , hDif , lDY )
newVector3D( vL , Lights[i2].x , 300 , Lights[i2].y , Lights[i2].x - ( spr.x + x ) , -300 , Lights[i2].y - ( spr.y + y ) )
anIX = getAngleBetweenVec3D( v1 , vL )
noEffect = FALSE ; noXEffect = FALSE ; noYEffect = FALSE
dist = SQR( POW( ( ( spr.x + x ) - Lights[i2].x ) , 2 ) + POW( ( ( spr.y + y ) - Lights[i2].y ) , 2 ) )
dist = Lights[i2].range - dist
IF anIX < 0 THEN anIX = 0
anIX = 1.0 - anIX
IF dist > 0
dist = dist / Lights[i2].range
dist = ( dist ) * anIX
dist = cBR( dist , 0 , 1.0 )
clr.r = clr.r + ( Lights[i2].color.r - clr.r ) *dist ; clr.g = clr.g + ( Lights[i2].color.g - clr.g ) * dist ; clr.b = clr.b + ( Lights[i2].color.b - clr.b ) * dist
ENDIF
ENDIF
NEXT
ENDIF
value = tMap[ i ]
IF bAND(ASR(value,24), 0xff) <> 0x00
clr.r = bAND( value, 0xff ) + ( clr.r - bAND( value, 0xff ) ) / 2.0
clr.g = bAND( ASR( value , 8 ) , 0xff ) + ( clr.g - bAND( ASR( value , 8 ) , 0xff ) ) / 2.0
clr.b = bAND( ASR( value , 16 ) , 0xff ) + ( clr.b - bAND( ASR( value , 16 ) , 0xff ) ) / 2.0
SETPIXEL spr.x + x , spr.y + y , RGB( clr.r , clr.g , clr.b )
ENDIF
clr.r = Ambient.r ; clr.g = Ambient.g ; clr.b = Ambient.b
NEXT
ENDFUNCTION
FUNCTION cB: value , minimum , maximum
IF minimum > maximum THEN SWAP minimum , maximum
IF value < minimum THEN RETURN minimum
IF value > maximum THEN RETURN maximum
RETURN value
ENDFUNCTION
FUNCTION cBR: value , minimum , maximum
IF minimum > maximum THEN SWAP minimum , maximum
IF value < minimum THEN RETURN minimum
IF value > maximum THEN RETURN maximum
RETURN value
ENDFUNCTION
FUNCTION updateLightMap: width% , height% , ambient AS vRGB
LOCAL lXL% , lXR% , lYU% , lYD% , dist# , scaleL#
FOR i = 0 TO width - 1
FOR i2 = 0 TO height - 1
LightMap[i][i2].r = ambient.r
LightMap[i][i2].g = ambient.g
LightMap[i][i2].b = ambient.b // Fill Lightmap with ambient light...
NEXT
NEXT
FOR i = 0 TO LightsMax - 1
IF Lights[i].exist
// IF Lights[i].x < 0 THEN Lights[i].x = 0 ; IF Lights[i].x > width - 1 THEN Lights[i].x = width - 1
// IF Lights[i].y < 0 THEN Lights[i].y = 0 ; IF Lights[i].y > height - 1 THEN Lights[i].y = height - 1
lXL = Lights[i].x - Lights[i].range ; lXR = Lights[i].x + Lights[i].range
IF lXL < 0 THEN lXL = 0 ; IF lXR > width - 1 THEN lXR = width - 1
lYD = Lights[i].y - Lights[i].range ; lYU = Lights[i].y + Lights[i].range
IF lYD < 0 THEN lYD = 0 ; IF lYU > height - 1 THEN lYU = height - 1
FOR i2 = lXL TO lXR
FOR i3 = lYD TO lYU
dist = SQR( POW( ( i2 - Lights[i].x ) , 2 ) + POW( ( i3 - Lights[i].y ) , 2 ) )
IF dist < Lights[i].range
scaleL = ( Lights[i].range - dist ) / Lights[i].range
LightMap[i2][i3].r = LightMap[i2][i3].r + ( Lights[i].color.r - LightMap[i2][i3].r ) * scaleL
LightMap[i2][i3].g = LightMap[i2][i3].g + ( Lights[i].color.g - LightMap[i2][i3].g ) * scaleL
LightMap[i2][i3].b = LightMap[i2][i3].b + ( Lights[i].color.b - LightMap[i2][i3].b ) * scaleL
ENDIF
NEXT
NEXT
ENDIF
NEXT
ENDFUNCTION
FUNCTION drawLightMap: width% , height% // for testing purpose, draw the lightmap only
FOR i = 0 TO width - 1
FOR i2 = 0 TO height - 1
SETPIXEL i , i2 , RGB( LightMap[i][i2].r , LightMap[i][i2].g , LightMap[i][i2].b )
NEXT
NEXT
ENDFUNCTION
Die benötigten Sprites sind angehängt, einfach in ein neues Projektverzeichniss in media\Sprites einfügen...
DrawLightMap und initLightMap habe ich nur zum Testen mit im Code.
mache mich heute an die Berechnung der passenden Normalvektoren der Dreiecke, dabei werde ich für jedes zweierpaar dreiecke ( 1 Pixel ) einen Interpolierten Mittelvektor aus den beiden Normalvektoren bestimmen.
ganz genau ! :whistle:
Quote from: nabz32 on 2015-Jan-03
mache mich heute an die Berechnung der passenden Normalvektoren der Dreiecke, dabei werde ich für jedes zweierpaar dreiecke ( 1 Pixel ) einen Interpolierten Mittelvektor aus den beiden Normalvektoren bestimmen.
Gesundheit! ;)
läuft nun schon besser das ganze,
nur habe ich das Problem, dass Das Licht wenn es im Objekt ist einen Schatten wirft.
Glaube das die Normalen falsch berechnet sind, werde nochmal reinschauen.
Hier das ganze bis jetzt:
// --------------------------------- //
// Project: 2DLight
// Start: Friday, January 02, 2015
// IDE Version: 12.312
CONSTANT LightsMax = 10
CONSTANT SpriteMax = 100
GLOBAL LightAngle#
TYPE vRGB
r% ; g% ; b%
ENDTYPE
TYPE light
color AS vRGB
range% // range of light ( Radius! )
kind% // kind of light ( other light reduction kinds till the end of the light range
exist%
x%
y%
ENDTYPE
TYPE sprite
srcTex$
srcH$
srcS$
iD%
x% ; y%
ENDTYPE
TYPE vec3D
dX#
dY#
dZ#
ENDTYPE
GLOBAL LightMap[] AS vRGB
GLOBAL Ambient AS vRGB
GLOBAL Lights[] AS light
main()
FUNCTION dotP: vector1 AS vec3D , vector2 AS vec3D
RETURN vector1.dX * vector2.dX + vector1.dY * vector2.dY + vector1.dZ * vector2.dZ
ENDFUNCTION
FUNCTION crossP AS vec3D: v1 AS vec3D , v2 AS vec3D , n AS vec3D
n.dX = ( v1.dY * v2.dZ ) - ( v1.dZ * v2.dY )
n.dY = ( v1.dZ * v2.dX ) - ( v1.dX * v2.dZ )
n.dZ = ( v1.dX * v2.dY ) - ( v1.dY * v2.dX )
ENDFUNCTION
FUNCTION magnitude: v AS vec3D
RETURN SQR( v.dX * v.dX + v.dY * v.dY + v.dZ * v.dZ )
ENDFUNCTION
FUNCTION newSprite AS sprite: s AS sprite , iDG , sT$ , sH$ , sS$ , x , y
s.srcTex$ = sT$ ; s.srcH$ = sH$ ; s.srcS$ = sS$ ; s.iD = iDG ; s.x = x ; s.y = y
ENDFUNCTION
FUNCTION newVector3D AS vec3D: v AS vec3D , dX% , dY% , dZ%
v.dX = dX ; v.dY = dY ; v.dZ = dZ
ENDFUNCTION
FUNCTION getAngleBetweenVec3D: v1 AS vec3D , v2 AS vec3D
RETURN dotP( v1 , v2 ) / ( magnitude( v1 ) * magnitude( v2 ) )
ENDFUNCTION
FUNCTION main:
LOCAL width% , height% , white AS vRGB , blue AS vRGB , red AS vRGB , ball AS sprite , ball2 AS sprite
LOCAL mX% , mY% , b1% , b2%
width = 320 ; height = 240
Ambient.r = 0 ; Ambient.g = 0 ; Ambient.b = 0
white.r = 255 ; white.g = 255 ; white.b = 255
blue.r = 120 ; blue.g = 120 ; blue.b = 255
red.r = 60 ; red.g = 255 ; red.b = 60
newSprite( ball , 100 , "bBall.bmp" , "bBallH.bmp" , "bBallS.bmp" , 160 , 120 )
newSprite( ball2 , 101 , "bBall.bmp" , "bBallH2.bmp" , "bBallS.bmp" , 320 , 240 )
SETCURRENTDIR("Media/Sprites") // go to media files
DIM LightMap[width][height] ; DIM Lights[LightsMax]
Lights[0].exist = TRUE ; Lights[0].x = 160 ; Lights[0].y = 120 ; Lights[0].range = 250 ; Lights[0].color = white
Lights[1].exist = TRUE ; Lights[1].x = 300 ; Lights[1].y = 200 ; Lights[1].range = 450 ; Lights[1].color = blue
Lights[2].exist = TRUE ; Lights[2].x = 60 ; Lights[2].y = 60 ; Lights[2].range = 50 ; Lights[2].color = red
WHILE NOT KEY( 30 )
MOUSESTATE mX , mY , b1 , b2
Lights[0].x = mX ; Lights[0].y = mY
// updateLightMap( width , height , Ambient )
X_MAKE2D
// drawLightMap( width , height )
drawLightSprite( ball ) ; drawLightSprite( ball2 )
PRINT LightAngle , 200 , 200
SHOWSCREEN
WEND
ENDFUNCTION
FUNCTION drawLightSprite: spr AS sprite
LOCAL w% , h% , w1% , h1% , w2% , h2% , tMap%[] , hMap%[] , x% , y% , value% , turn% , anIX# , anIZ# , hDif#
LOCAL hLD% , hRD% , hLU% , hRU% , ok% , anX# , anZ# , lDX# , lDY# , lDXU# , lDYU#
LOCAL hL# , hR# , hU# , hD# , dAn#
LOCAL dist# , clr AS vRGB , v1 AS vec3D , v2 AS vec3D , vL AS vec3D
ok = LOADSPRITEMEM( spr.srcTex$ , w1 , h1 , tMap[] )
IF NOT ok THEN RETURN FALSE
ok = LOADSPRITEMEM( spr.srcH$ , w2 , h2 , hMap[] )
IF NOT ok THEN RETURN FALSE
IF w2 <> w1 OR h2 <> h1 THEN RETURN FALSE // hMap has to be the same size as the texture size for this to work...
w = w1 ; h = h1 ; clr.r = Ambient.r ; clr.g = Ambient.g ; clr.b = Ambient.b
LightAngle = ATAN( ( ( h / 2 ) + spr.y - Lights[0].y ) , ( ( w / 2.0 ) + spr.x - Lights[0].x ) )
FOR i = 0 TO BOUNDS( hMap[] , 0 ) - 1
x = MOD( i , w ) ; y = i / w ; value = hMap[ i ]
IF bAND(ASR(value,24), 0xff) <> 0x00 // not pink "alpha" color...
hLD = value
hRD = hMap[ cB( ( x + 1 ) , 0 , ( w - 1 ) ) + ( y * w ) ]
hLU = hMap[ x + ( cB( ( y + 1 ) , 0 , ( h - 1 ) ) * w ) ]
hRU = hMap[ cB( ( x + 1 ) , 0 , ( w - 1 ) ) + ( cB( ( y + 1 ) , 0 , ( h - 1 ) ) * w ) ]
IF hRD = 0xFFFF0080 THEN hRD = value ; IF hLU = 0xFFFF0080 THEN hLU = value ; IF hRU = 0xFFFF0080 THEN hRU = value // not pink "alpha" color...
hLD = bAND( hLD , 0xff ) ; hRD = bAND( hRD , 0xff ) ; hLU = bAND( hLU , 0xff ) ; hRU = bAND( hRU , 0xff )
hL = hLD + ( hLU - hLD ) / 2.0 ; hR = hRD + ( hRU - hRD ) / 2.0
hU = hLU + ( hRU - hLU ) / 2.0 ; hD = hLD + ( hRD - hLD ) / 2.0
FOR i2 = 0 TO LightsMax - 1
IF Lights[i2].exist
lDX = Lights[i2].x - ( spr.x + ( w / 2.0 ) ) ; lDY = Lights[i2].y - ( spr.y + ( h / 2.0 ) )
lDXU = lDX / ABS( MAX( lDX , lDY ) ) ; lDYU = lDY / ABS( MAX( lDX , lDY ) )
getnormalVector(hLU , hRU , hLD , hRD , v1 )
newVector3D( vL , lDX , -1 , lDY )
anIX = getAngleBetweenVec3D( v1 , vL )
dist = SQR( POW( ( ( spr.x + x ) - Lights[i2].x ) , 2 ) + POW( ( ( spr.y + y ) - Lights[i2].y ) , 2 ) )
dist = Lights[i2].range - dist
anIX = 1.0 + anIX
IF anIX > 1.0 THEN anIX = 1.0
IF dist > 0
dist = dist / Lights[i2].range
dist = ( dist ) * anIX
// dist = cBR( dist , 0 , 1.0 )
clr.r = clr.r + ( Lights[i2].color.r - clr.r ) *dist ; clr.g = clr.g + ( Lights[i2].color.g - clr.g ) * dist ; clr.b = clr.b + ( Lights[i2].color.b - clr.b ) * dist
ENDIF
ENDIF
NEXT
ENDIF
value = tMap[ i ]
IF bAND(ASR(value,24), 0xff) <> 0x00
clr.r = bAND( value, 0xff ) + ( clr.r - bAND( value, 0xff ) ) / 2.0
clr.g = bAND( ASR( value , 8 ) , 0xff ) + ( clr.g - bAND( ASR( value , 8 ) , 0xff ) ) / 2.0
clr.b = bAND( ASR( value , 16 ) , 0xff ) + ( clr.b - bAND( ASR( value , 16 ) , 0xff ) ) / 2.0
SETPIXEL spr.x + x , spr.y + y , RGB( clr.r , clr.g , clr.b )
ENDIF
clr.r = Ambient.r ; clr.g = Ambient.g ; clr.b = Ambient.b
NEXT
ENDFUNCTION
FUNCTION getnormalVector AS vec3D: hLU% , hRU% , hLD% , hRD% , n AS vec3D
LOCAL P1 AS vec3D , P2 AS vec3D , P3 AS vec3D , n1 AS vec3D , n2 AS vec3D , c1 AS vec3D , c2 AS vec3D , c3 AS vec3D
IF ABS( ( hLU - hRD ) ) > ABS( ( hRU - hLD ) )// turn triangles...
P1.dX = 0 ; P1.dY = hLD ; P1.dZ = 0 ; P2.dX = 0 ; P2.dY = hLU ; P2.dZ = 1 ; P3.dX = 1 ; P3.dY = hRD ; P3.dZ = 0
crossP( P1 , P2 , c1 ) ; crossP( P2 , P3 , c2 ) ; crossP( P3 , P1 , c3 )
n1.dX = c1.dX + c2.dX + c3.dX
n1.dY = c1.dY + c2.dY + c3.dY
n1.dZ = c1.dZ + c2.dZ + c3.dZ
P1.dX = 1 ; P1.dY = hRU ; P1.dZ = 1 ; P2.dX = 1 ; P2.dY = hRD ; P2.dZ = 0 ; P3.dX = 0 ; P3.dY = hLU ; P3.dZ = 1
crossP( P1 , P2 , c1 ) ; crossP( P2 , P3 , c2 ) ; crossP( P3 , P1 , c3 )
n2.dX = c1.dX + c2.dX + c3.dX
n2.dY = c1.dY + c2.dY + c3.dY
n2.dZ = c1.dZ + c2.dZ + c3.dZ
n.dX = n1.dX + ( n2.dX - n1.dX ) / 2.0
n.dY = n1.dY + ( n2.dY - n1.dY ) / 2.0
n.dZ = n1.dZ + ( n2.dZ - n1.dZ ) / 2.0
ELSE
P1.dX = 0 ; P1.dY = hLU ; P1.dZ = 1 ; P2.dX = 1 ; P2.dY = hRU ; P2.dZ = 1 ; P3.dX = 0 ; P3.dY = hLD ; P3.dZ = 0
crossP( P1 , P2 , c1 ) ; crossP( P2 , P3 , c2 ) ; crossP( P3 , P1 , c3 )
n1.dX = c1.dX + c2.dX + c3.dX
n1.dY = c1.dY + c2.dY + c3.dY
n1.dZ = c1.dZ + c2.dZ + c3.dZ
P1.dX = 1 ; P1.dY = hRD ; P1.dZ = 0 ; P2.dX = 0 ; P2.dY = hLD ; P2.dZ = 0 ; P3.dX = 1 ; P3.dY = hRU ; P3.dZ = 1
crossP( P1 , P2 , c1 ) ; crossP( P2 , P3 , c2 ) ; crossP( P3 , P1 , c3 )
n2.dX = c1.dX + c2.dX + c3.dX
n2.dY = c1.dY + c2.dY + c3.dY
n2.dZ = c1.dZ + c2.dZ + c3.dZ
n.dX = n1.dX + ( n2.dX - n1.dX ) / 2.0
n.dY = n1.dY + ( n2.dY - n1.dY ) / 2.0
n.dZ = n1.dZ + ( n2.dZ - n1.dZ ) / 2.0
ENDIF
ENDFUNCTION
FUNCTION cB: value , minimum , maximum
IF minimum > maximum THEN SWAP minimum , maximum
IF value < minimum THEN RETURN minimum
IF value > maximum THEN RETURN maximum
RETURN value
ENDFUNCTION
FUNCTION cBR: value , minimum , maximum
IF minimum > maximum THEN SWAP minimum , maximum
IF value < minimum THEN RETURN minimum
IF value > maximum THEN RETURN maximum
RETURN value
ENDFUNCTION
FUNCTION updateLightMap: width% , height% , ambient AS vRGB
LOCAL lXL% , lXR% , lYU% , lYD% , dist# , scaleL#
FOR i = 0 TO width - 1
FOR i2 = 0 TO height - 1
LightMap[i][i2].r = ambient.r
LightMap[i][i2].g = ambient.g
LightMap[i][i2].b = ambient.b // Fill Lightmap with ambient light...
NEXT
NEXT
FOR i = 0 TO LightsMax - 1
IF Lights[i].exist
lXL = Lights[i].x - Lights[i].range ; lXR = Lights[i].x + Lights[i].range
IF lXL < 0 THEN lXL = 0 ; IF lXR > width - 1 THEN lXR = width - 1
lYD = Lights[i].y - Lights[i].range ; lYU = Lights[i].y + Lights[i].range
IF lYD < 0 THEN lYD = 0 ; IF lYU > height - 1 THEN lYU = height - 1
FOR i2 = lXL TO lXR
FOR i3 = lYD TO lYU
dist = SQR( POW( ( i2 - Lights[i].x ) , 2 ) + POW( ( i3 - Lights[i].y ) , 2 ) )
IF dist < Lights[i].range
scaleL = ( Lights[i].range - dist ) / Lights[i].range
LightMap[i2][i3].r = LightMap[i2][i3].r + ( Lights[i].color.r - LightMap[i2][i3].r ) * scaleL
LightMap[i2][i3].g = LightMap[i2][i3].g + ( Lights[i].color.g - LightMap[i2][i3].g ) * scaleL
LightMap[i2][i3].b = LightMap[i2][i3].b + ( Lights[i].color.b - LightMap[i2][i3].b ) * scaleL
ENDIF
NEXT
NEXT
ENDIF
NEXT
ENDFUNCTION
FUNCTION drawLightMap: width% , height% // for testing purpose, draw the lightmap only
FOR i = 0 TO width - 1
FOR i2 = 0 TO height - 1
SETPIXEL i , i2 , RGB( LightMap[i][i2].r , LightMap[i][i2].g , LightMap[i][i2].b )
NEXT
NEXT
ENDFUNCTION
Sieht schonmal fast richtig aus :)
Man kann natürlich auch die Normalen in einer vec3D Array vorgenerieren um Leistung zu sparen.
Auch werde ich noch zwei Skalierungsfaktoren für die HeightMap hinzufügen um nicht soviele Normalvektoren speichern zu müssen.
Du machst mir echt Angst ^^
Habe nurnoch die Höhe des Lichtvektors der Lichtgröße anpassen müssen, sieht jetzt deutlich besser aus.
Habe auch mal ne Heightmap für einen Basketball gebastelt =D
Und hier der Code: ( Habe ihn noch etwas aufgeräumt )
// --------------------------------- //
// Project: 2DLight
// Start: Friday, January 02, 2015
// IDE Version: 12.312
CONSTANT LightsMax = 10
CONSTANT SpriteMax = 100
TYPE vRGB
r% ; g% ; b%
ENDTYPE
TYPE light
color AS vRGB
range% // range of light ( Radius! )
kind% // kind of light ( other light reduction kinds till the end of the light range
exist%
x%
y%
ENDTYPE
TYPE sprite
srcTex$
srcH$
srcS$
iD%
x% ; y%
ENDTYPE
TYPE vec3D
dX#
dY#
dZ#
ENDTYPE
GLOBAL LightMap[] AS vRGB
GLOBAL Ambient AS vRGB
GLOBAL Lights[] AS light
main()
FUNCTION dotP: vector1 AS vec3D , vector2 AS vec3D
RETURN vector1.dX * vector2.dX + vector1.dY * vector2.dY + vector1.dZ * vector2.dZ
ENDFUNCTION
FUNCTION crossP AS vec3D: v1 AS vec3D , v2 AS vec3D , n AS vec3D
n.dX = ( v1.dY * v2.dZ ) - ( v1.dZ * v2.dY )
n.dY = ( v1.dZ * v2.dX ) - ( v1.dX * v2.dZ )
n.dZ = ( v1.dX * v2.dY ) - ( v1.dY * v2.dX )
ENDFUNCTION
FUNCTION magnitude: v AS vec3D
RETURN SQR( v.dX * v.dX + v.dY * v.dY + v.dZ * v.dZ )
ENDFUNCTION
FUNCTION newSprite AS sprite: s AS sprite , iDG , sT$ , sH$ , sS$ , x , y
s.srcTex$ = sT$ ; s.srcH$ = sH$ ; s.srcS$ = sS$ ; s.iD = iDG ; s.x = x ; s.y = y
ENDFUNCTION
FUNCTION newVector3D AS vec3D: v AS vec3D , dX% , dY% , dZ%
v.dX = dX ; v.dY = dY ; v.dZ = dZ
ENDFUNCTION
FUNCTION getAngleBetweenVec3D: v1 AS vec3D , v2 AS vec3D
RETURN dotP( v1 , v2 ) / ( magnitude( v1 ) * magnitude( v2 ) )
ENDFUNCTION
FUNCTION new2DLight AS light: nr% , x% , y% , range% , kind% , r% , g% , b%
Lights[nr].exist = TRUE ; Lights[nr].x = x ; Lights[nr].y = y ; Lights[nr].range = range
Lights[nr].color.r = r ; Lights[nr].color.g = g ; Lights[nr].color.b = b ; Lights[nr].kind = kind
ENDFUNCTION
FUNCTION main:
LOCAL width% , height% , ball AS sprite , ball2 AS sprite
LOCAL mX% , mY% , b1% , b2%
width = 320 ; height = 240 // size of LightMap ( Just for testing )
Ambient.r = 0 ; Ambient.g = 0 ; Ambient.b = 0
DIM LightMap[width][height] ; DIM Lights[LightsMax]
SETCURRENTDIR("Media/Sprites") // go to media files
newSprite( ball , 100 , "bBall.bmp" , "bBallH.bmp" , "bBallS.bmp" , 160 , 120 )
newSprite( ball2 , 101 , "bBall.bmp" , "bBallH2.bmp" , "bBallS.bmp" , 320 , 240 )
new2DLight( 0 , 0 , 0 , 800 , 0 , 255 , 220 , 220 )
WHILE NOT KEY( 30 )
MOUSESTATE mX , mY , b1 , b2
Lights[0].x = mX ; Lights[0].y = mY
IF b2 = TRUE ; Lights[0].kind = 1 ; ELSE ; Lights[0].kind = 0 ; ENDIF
updateLightMap( width , height , Ambient )
X_MAKE2D
drawLightMap( width , height )
drawLightSprite( ball ) ; drawLightSprite( ball2 )
SHOWSCREEN
WEND
ENDFUNCTION
FUNCTION drawLightSprite: spr AS sprite
LOCAL w1% , h1% , w2% , h2% , tMap%[] , hMap%[] , x% , y% , value% , anIN#
LOCAL hLD% , hRD% , hLU% , hRU% , ok%
LOCAL dist# , clr AS vRGB , v1 AS vec3D , v2 AS vec3D , vL AS vec3D
ok = LOADSPRITEMEM( spr.srcTex$ , w1 , h1 , tMap[] )
IF NOT ok THEN RETURN FALSE
ok = LOADSPRITEMEM( spr.srcH$ , w2 , h2 , hMap[] )
IF NOT ok THEN RETURN FALSE
IF w2 <> w1 OR h2 <> h1 THEN RETURN FALSE // hMap has to be the same size as the texture size for this to work...
clr.r = Ambient.r ; clr.g = Ambient.g ; clr.b = Ambient.b
FOR i = 0 TO BOUNDS( hMap[] , 0 ) - 1
x = MOD( i , w1 ) ; y = i / w1 ; value = hMap[ i ]
IF bAND(ASR(value,24), 0xff) <> 0x00 // not pink "alpha" color...
hLD = value
hRD = hMap[ cB( ( x + 1 ) , 0 , ( w1 - 1 ) ) + ( y * w1 ) ]
hLU = hMap[ x + ( cB( ( y + 1 ) , 0 , ( h1 - 1 ) ) * w1 ) ]
hRU = hMap[ cB( ( x + 1 ) , 0 , ( w1 - 1 ) ) + ( cB( ( y + 1 ) , 0 , ( h1 - 1 ) ) * w1 ) ]
// check for pink "alpha" on the points around...
IF bAND(ASR(hRD,24), 0xff) = 0x00 ; hRD = 0 ; ELSE ; hRD = bAND( hRD , 0xff ) ; ENDIF
IF bAND(ASR(hLU,24), 0xff) = 0x00 ; hLU = 0 ; ELSE ; hLU = bAND( hLU , 0xff ) ; ENDIF
IF bAND(ASR(hRU,24), 0xff) = 0x00 ; hRU = 0 ; ELSE ; hRU = bAND( hRU , 0xff ) ; ENDIF
hLD = bAND( hLD , 0xff )
FOR i2 = 0 TO LightsMax - 1 // Go through all Lights and get an interpolated Light value based on Normals
IF Lights[i2].exist
dist = SQR( POW( ( ( spr.x + x ) - Lights[i2].x ) , 2 ) + POW( ( ( spr.y + y ) - Lights[i2].y ) , 2 ) )
dist = Lights[i2].range - dist
IF dist > 0
getnormalVector(hLU , hRU , hLD , hRD , v1 ) // Calculate the normal vector
newVector3D( vL , ( Lights[i2].x - ( spr.x + x ) ) , -Lights[i2].range / 2.0 , ( Lights[i2].y - ( spr.y + y ) ) ) // generate the Light Vector
anIN = getAngleBetweenVec3D( v1 , vL ) ; anIN = 1.0 + anIN ; IF anIN > 1.0 THEN anIN = 1.0
dist = dist / Lights[i2].range ; dist = ( dist ) * anIN
clr.r = clr.r + ( Lights[i2].color.r - clr.r ) *dist ; clr.g = clr.g + ( Lights[i2].color.g - clr.g ) * dist ; clr.b = clr.b + ( Lights[i2].color.b - clr.b ) * dist
ENDIF
ENDIF
NEXT
ENDIF
value = tMap[ i ] // Draw the Pixel by drawing the mean value of the texture pixel and Light Pixel
IF bAND(ASR(value,24), 0xff) <> 0x00
clr.r = bAND( value, 0xff ) + ( clr.r - bAND( value, 0xff ) ) / 2.0
clr.g = bAND( ASR( value , 8 ) , 0xff ) + ( clr.g - bAND( ASR( value , 8 ) , 0xff ) ) / 2.0
clr.b = bAND( ASR( value , 16 ) , 0xff ) + ( clr.b - bAND( ASR( value , 16 ) , 0xff ) ) / 2.0
SETPIXEL spr.x + x , spr.y + y , RGB( clr.r , clr.g , clr.b )
ENDIF
clr.r = Ambient.r ; clr.g = Ambient.g ; clr.b = Ambient.b
NEXT
ENDFUNCTION
FUNCTION getnormalVector AS vec3D: hLU% , hRU% , hLD% , hRD% , n AS vec3D
LOCAL P1 AS vec3D , P2 AS vec3D , P3 AS vec3D , n1 AS vec3D , n2 AS vec3D , c1 AS vec3D , c2 AS vec3D , c3 AS vec3D
IF ABS( ( hLU - hRD ) ) > ABS( ( hRU - hLD ) )// turn triangles...
P1.dX = 0 ; P1.dY = hLD ; P1.dZ = 0 ; P2.dX = 0 ; P2.dY = hLU ; P2.dZ = 1 ; P3.dX = 1 ; P3.dY = hRD ; P3.dZ = 0
crossP( P1 , P2 , c1 ) ; crossP( P2 , P3 , c2 ) ; crossP( P3 , P1 , c3 )
n1.dX = c1.dX + c2.dX + c3.dX
n1.dY = c1.dY + c2.dY + c3.dY
n1.dZ = c1.dZ + c2.dZ + c3.dZ
P1.dX = 1 ; P1.dY = hRU ; P1.dZ = 1 ; P2.dX = 1 ; P2.dY = hRD ; P2.dZ = 0 ; P3.dX = 0 ; P3.dY = hLU ; P3.dZ = 1
crossP( P1 , P2 , c1 ) ; crossP( P2 , P3 , c2 ) ; crossP( P3 , P1 , c3 )
n2.dX = c1.dX + c2.dX + c3.dX
n2.dY = c1.dY + c2.dY + c3.dY
n2.dZ = c1.dZ + c2.dZ + c3.dZ
n.dX = n1.dX + ( n2.dX - n1.dX ) / 2.0
n.dY = n1.dY + ( n2.dY - n1.dY ) / 2.0
n.dZ = n1.dZ + ( n2.dZ - n1.dZ ) / 2.0
ELSE
P1.dX = 0 ; P1.dY = hLU ; P1.dZ = 1 ; P2.dX = 1 ; P2.dY = hRU ; P2.dZ = 1 ; P3.dX = 0 ; P3.dY = hLD ; P3.dZ = 0
crossP( P1 , P2 , c1 ) ; crossP( P2 , P3 , c2 ) ; crossP( P3 , P1 , c3 )
n1.dX = c1.dX + c2.dX + c3.dX
n1.dY = c1.dY + c2.dY + c3.dY
n1.dZ = c1.dZ + c2.dZ + c3.dZ
P1.dX = 1 ; P1.dY = hRD ; P1.dZ = 0 ; P2.dX = 0 ; P2.dY = hLD ; P2.dZ = 0 ; P3.dX = 1 ; P3.dY = hRU ; P3.dZ = 1
crossP( P1 , P2 , c1 ) ; crossP( P2 , P3 , c2 ) ; crossP( P3 , P1 , c3 )
n2.dX = c1.dX + c2.dX + c3.dX
n2.dY = c1.dY + c2.dY + c3.dY
n2.dZ = c1.dZ + c2.dZ + c3.dZ
n.dX = n1.dX + ( n2.dX - n1.dX ) / 2.0
n.dY = n1.dY + ( n2.dY - n1.dY ) / 2.0
n.dZ = n1.dZ + ( n2.dZ - n1.dZ ) / 2.0
ENDIF
ENDFUNCTION
FUNCTION cB: value , minimum , maximum
IF minimum > maximum THEN SWAP minimum , maximum
IF value < minimum THEN RETURN minimum
IF value > maximum THEN RETURN maximum
RETURN value
ENDFUNCTION
FUNCTION cBR AS float: value# , minimum# , maximum#
IF minimum > maximum THEN SWAP minimum , maximum
IF value < minimum THEN RETURN minimum
IF value > maximum THEN RETURN maximum
RETURN value
ENDFUNCTION
FUNCTION updateLightMap: width% , height% , ambient AS vRGB
LOCAL lXL% , lXR% , lYU% , lYD% , dist# , scaleL#
FOR i = 0 TO width - 1
FOR i2 = 0 TO height - 1
LightMap[i][i2].r = ambient.r
LightMap[i][i2].g = ambient.g
LightMap[i][i2].b = ambient.b // Fill Lightmap with ambient light...
NEXT
NEXT
FOR i = 0 TO LightsMax - 1
IF Lights[i].exist
lXL = Lights[i].x - Lights[i].range ; lXR = Lights[i].x + Lights[i].range
IF lXL < 0 THEN lXL = 0 ; IF lXR > width - 1 THEN lXR = width - 1
lYD = Lights[i].y - Lights[i].range ; lYU = Lights[i].y + Lights[i].range
IF lYD < 0 THEN lYD = 0 ; IF lYU > height - 1 THEN lYU = height - 1
FOR i2 = lXL TO lXR
FOR i3 = lYD TO lYU
dist = SQR( POW( ( i2 - Lights[i].x ) , 2 ) + POW( ( i3 - Lights[i].y ) , 2 ) )
IF dist < Lights[i].range
scaleL = ( Lights[i].range - dist ) / Lights[i].range
LightMap[i2][i3].r = LightMap[i2][i3].r + ( Lights[i].color.r - LightMap[i2][i3].r ) * scaleL
LightMap[i2][i3].g = LightMap[i2][i3].g + ( Lights[i].color.g - LightMap[i2][i3].g ) * scaleL
LightMap[i2][i3].b = LightMap[i2][i3].b + ( Lights[i].color.b - LightMap[i2][i3].b ) * scaleL
ENDIF
NEXT
NEXT
ENDIF
NEXT
ENDFUNCTION
FUNCTION drawLightMap: width% , height% // for testing purpose, draw the lightmap only
FOR i = 0 TO width - 1
FOR i2 = 0 TO height - 1
SETPIXEL i , i2 , RGB( LightMap[i][i2].r , LightMap[i][i2].g , LightMap[i][i2].b )
NEXT
NEXT
ENDFUNCTION
Edit:
Media Dateien vergessen, nun im Anhang.
Schöner Effekt, sieht gut aus! :booze:
Wie sieht da die Performance aus, könnte man das in größerem Maßstab live in einem Spiel nutzen?
Generell gibt es genau für solche Sachen Shader, könntest du dir auch mal anschauen (kann dir dabei helfen, die GLBasic Limitierungen zu beheben, wenn du willst). Allerdings wäre das dann nur Desktop-Plattform.
Shaderprogrammierung habe ich bis jetzt noch nie gemacht,
nur mal ein paar vorgefertigte in Darkbasic damals getestet...
Solange das Spiel eine niedrige Aufloesung hat, kein Problem von der Performance her
( wenn ich endlich mal dazu kommen wuerde die Normal maps vorzugenerieren und sie nicht in jedem Frame neu zu berechnen).
Wenn man diesen Effekt immer fuer den gesamten Bildausschnitt berechnet, waere es auch kein Problem wenn man richtig viele dieser Sprites nutzt ( 2D Z hinzufuegen, abfragen welcher sprite fuer diesen Pixel in Frage kommt ).
Dann haette man aber das Problem, dass die Sprites nicht drehbar waeren bzw. man muesste irgendwie in Software vor der Abfrage rotieren.
Eine andere moeglichkeit waere eine kleinere Heightmap und Normalmap fuer den Sprite, man muesste zwar wieder jeden Pixel abfragen, die Berechnung des Lichteinfalls wuerde aber nur fuer eine Gruppe von Pixeln berechnet.
Ist der sprite etwas pixelig hochgescaletes, wuerde dies sogar noch ohne Interpolation gut aussehen.
Wollte mir damit nur beweisen, dass ich so einen Effekt mit nem Sprite und ner HMap
hinbekomme.
Edit:
Die Anzahl der Lichtquellen bestimmt maßgeblich wie oft berechnet werden muss.