Odd problem with blending (I think) - help!
Blitz3D Forums/Blitz3D Programming/Odd problem with blending (I think) - help!
| ||
Okay this is slightly complicated but I'll explain as best as I can. I'm making a sort of top down space game. The camera is at (0, 900, 0) and pointed straight down. The camera does not move. My ships move along the X and Z axes but are always at 0 on the Y axis. I wanted to have a background of twinkling stars. First I made a Plane entity, textured it with stars, and positioned it at (0, -40, 0). This gave me a starry background. To make the stars twinkle I made a texture that is mostly white with some darker lines in it, and applied to another plane below the stars at (0, -50, 0). I set my stars plane to blend mode #2 (MULTIPLY). Then I scroll the white/dark lines texture. The result is perfect - I get nice stars that occasionally dim for a moment giving a nice overall twinkling impression. The problem arises when I try to have my spaceships leave a trail of fire behind them. The way I do this is a trail of little fire-texture particles with the blend mode set to 3 (ADD). Without the starry background, it looks perfect. However when I have both at the same time, I get a strange problem. When the ship is near the centre of the screen, everything works fine, but when I move it to the edges, the particles stop showing up at all except where they go over the top of the ship. It's like a circle around the centre of the screen where they show up against the stars, and outside it they don't. I tried using Orthogonal projection and it made no difference. My particles are not going below the level of the planes at all. I think it's some sort of blending problem but I really don't know. Ideas, anyone? EDIT: This may or may not help explain what I'm doing: |
| ||
Do you really need to blend the particles using entityblend? I've never used EntityBlend before, so i don't know what effects it gives you. |
| ||
Your camera range may be set wrong. Or, your starry background is a sphere that is clipping the fire. OR, the starry background is a plane and the particles are in a plane which is so close to the starry background that those areas near the edge are swapping what's in front and what's in back cause there's not enough precision in the zbuffer. I think it's likely the last of these three. Set your camera range so that the ratio between near and far planes is as small as possible. ie, 0.1, 100 is worse than 1,100, or 0.1, 10. This will correct any zbuffer issues, but you still need to make sure that the particles aren't actually at the same Z detph as the stars... int he same plane as them, otherwise they'll never sort right. So move the stars firther away from the camera than the add blended stuff. |
| ||
Yep. With EntityBlend EN, 3 (ADD) it gives a very bright burning type thing where multiple particles overlap and generally looks extremely good. With the default blend (ALPHA) it's kind of drab and boring and dull and stuff. So, er, yeah. |
| ||
SSwift, Camera range is set to 10.0, 1000.0. I have confirmed it isn't Z-buffer issues. The stars plane is at -40.0, the particle quads are all above 0.0. I am also running in 32bit mode so there's a nice and accurate Z-buffer. I have tried camera ranges of (10.0, 1000.0), (500.0, 1000.0), (10.0, 2500.0), (500.0, 2500.0), and (10.0, 20000.0), (500.0, 20000.0). None made any difference to anything whatsoever in the slightest. |
| ||
I have done some testing and it turns out that the further away the camera is from the origin, the further from the camera the ship has to go before the particles become invisible. Odd. It means that at a sufficient distance they always show up but right near to it, they only show up in the very middle of the screen. |
| ||
Post your code. |
| ||
Okay there's quite a lot so I made a simple 100 line version to demonstrate the problem. Here's the code:Graphics3D 800, 600, 16, 2 ; Types Type Player Field EN Field Accelerate, Turn Field ZV# End Type Type Fire Field EN, X#, Z#, Age End Type ; Globals Global Cam ; Camera and lighting Cam = CreateCamera() : CameraRange Cam, 10.0, 2500.0 : CameraZoom Cam, 1.5 PositionEntity Cam, 0, 900, 0 : RotateEntity Cam, 90, 0, 0 L = CreateLight(2) : EntityParent L, Cam : PositionEntity L, 0, 0, 0 LightRange L, 10000.0 ; Backgrounds B1 = CreatePlane() : PositionEntity B1, 0, -50, 0 : EntityFX B1, 9 B2 = CreatePlane() : PositionEntity B2, 0, -40, 0 : EntityFX B2, 9 : EntityBlend B2, 2 BT1 = LoadTexture("Data\VLines.bmp") : ScaleTexture BT1, 512, 512 : EntityTexture B1, BT1 BT2 = LoadTexture("Data\Stars.bmp") : ScaleTexture BT2, 1200, 1200 : EntityTexture B2, BT2 ; Fire particle template FireEN = CreateQuad() : ScaleMesh FireEN, 20.0, 20.0, 1 : EntityFX FireEN, 1 : EntityBlend FireEN, 3 FireTex = LoadTexture("Data\Fire.bmp") : EntityTexture FireEN, FireTex HideEntity FireEN ; Player ship Me.Player = New Player Me\EN = LoadMesh("Data\Ship.b3d") ; Main loop While Not KeyHit(1) ; Ship controls Me\Turn = KeyDown(205) - KeyDown(203) Me\Accelerate = KeyDown(200) - KeyDown(208) ; Turning If Me\Turn <> 0 Roll# = CurveValue#(EntityRoll#(Me\EN), -40.0 * Me\Turn, 5.0) RotateEntity Me\EN, EntityPitch#(Me\EN), EntityYaw#(Me\EN), Roll# TurnEntity Me\EN, 0, -4 * Me\Turn, 0, True EndIf Roll# = CurveValue#(EntityRoll#(Me\EN), 00.0, 20.0) RotateEntity Me\EN, EntityPitch#(Me\EN), EntityYaw#(Me\EN), Roll# ; Moving Me\ZV# = Me\ZV# + 0.5 * Me\Accelerate If Me\ZV# > 18.0 Then Me\ZV# = 18.0 ElseIf Me\ZV# < 0.0 Then Me\ZV# = 0.0 MoveEntity Me\EN, 0, 0, Me\ZV# ; Fire trail For i = 1 To Int(Ceil#(Me\ZV# / 2.0)) F.Fire = New Fire : F\EN = CopyEntity(FireEN) PositionEntity F\EN, EntityX#(Me\EN), Rnd#(-10.0, 10.0), EntityZ#(Me\EN) RotateEntity F\EN, 0.0, EntityYaw#(Me\EN), 0.0 : MoveEntity F\EN, 0.0, 0.0, -30.0 F\X# = Rnd#(-2.0, 2.0) F\Z# = Rnd#(-2.0, 2.0) Next ; Make stars twinkle BT1V# = BT1V# + 0.002 PositionTexture BT1, 0.0, BT1V# UpdateFire UpdateWorld : RenderWorld : Flip Wend End ; Functions ------------------------------------------------------------------------------------------ ; Updates all fire particles Function UpdateFire() For F.Fire = Each Fire TranslateEntity F\EN, F\X#, 0.0, F\Z# PointEntity F\EN, Cam F\Age = F\Age + 1 If F\Age > 15 Then FreeEntity F\EN : Delete F Next End Function ; Creates a quad mesh Function CreateQuad(P = 0) If P Then EN = CreateMesh(P) Else EN = CreateMesh() s = CreateSurface(EN) v1 = AddVertex(s, -1.0, -1.0, 0.0, 0, 1) v2 = AddVertex(s, 1.0, -1.0, 0.0, 1, 1) v3 = AddVertex(s, 1.0, 1.0, 0.0, 1, 0) v4 = AddVertex(s, -1.0, 1.0, 0.0, 0, 0) AddTriangle s, v1, v2, v3 AddTriangle s, v1, v3, v4 Return EN End Function Function CurveValue#(Current#, Destination#, Curve#) Return Current# + ((Destination# - Current#) / Curve#) End Function |
| ||
Here's a download containing the code & media: http://www.marksweb.pwp.blueyonder.co.uk/files/test.zip |
| ||
I haven't checked through the code so this may not be it, but then it may be and it doesn't sound like you've considered it yet. Note that when an entity is set to ADD or MULTIPLY blend modes the z-buffer no longer applies to it. Now drawing order is determined simply by entity position, and whichever blended entity is closest to the camera is drawn before other blended entities. The important thing here however is that entity position and polygon position are two different things. It may be (especially if you are using a single surface particle system) that the entity position of the particles is further from the camera than the starry plane, even though the particle polygons are closer. |
| ||
Ah, that makes a lot of sense and would explain the 'symptoms' rather well. I'll try EntityOrdering my planes to the back then... EDIT: Well, as simple as that! Thanks :D I was making tbe mistake of considering polygon distance for Z-ordering rather than entity distance. So of course the middle of the plane was nearer to the camera than higher particles that were further away in the X/Z dimensions - UNTIL I MOVED THE CAMERA. Funny how the most puzzling problems come from the silliest mistakes. Thanks all :-) |
| ||
Not silly at all. I think the number 1 problem I contend with daily is draw order problems for semi-transparent polygons (including both alpha and blending.) |
| ||
i get the same problem, when something is off in the distance. |
| ||
Have you tried setting AmbientLight to somewhere about 180,180,180 dunno - just an idea... |
| ||
Just used entityblend for my fire particles, and it looks pretty awesome. Thanks for bringing that command to my attention :) Sorry for being OT! |
| ||
Watch out though 'cos add mode can be a wee bit slow on some older cards - or any strange blending mode for that matter. It does look extremely cool though :-) |