Skip to content

Quality Improvements

Narta Xaymar Dirks edited this page Nov 8, 2026 · 1 revision

Quality improvements

Things that look better or no longer break compared to the originals. None of them needs a change to your program.

Depth buffer

Blitz3D used a 16 or 24-bit buffer that is 0 at the near plane. It spends most of its precision close to the camera, and far surfaces flicker through each other (z-fighting).

BlitzLLVM writes the near plane of CameraRange as 1 and the far plane as 0 into a 32-bit float buffer, and the closer surface wins. The precision is almost even over the whole range, so distant surfaces that are close together stay apart without pushing near out.

A program can not see the buffer. ProjectedZ is the distance in front of the camera, and the depth argument of Graphics3D is not used.

Many lights

Blitz3D uses the fixed function lights of Direct3D 7. They are limited to eight for the whole scene, and the lights after the eighth do nothing.

BlitzLLVM keeps up to 127 visible lights per camera. Every draw gets its own set of eight, chosen on the CPU when the draw is made:

  • A light is rated by its brightness (the color of LightColor) times its attenuation (range over distance). The distance is measured to the closest point of the sphere around the entity's box, which is the most the light can do anywhere on the entity.
  • The eight best ratings are used. Lights rated below 1/512 are left out.
  • Negative lights, which darken, are rated by the size of their color, so a strong one is not left out for a weak positive one.
  • Directional lights are rated by their color alone. Spot cones are not taken into account.
  • With EntityLightChannel only the lights that share a channel with an entity are rated for it, so lights of other channels never use up one of its eight.
  • Planes, terrains and fullbright entities have no box and are not rated. They take the first eight lights that share a channel with them.

A scene with eight lights or fewer is lit exactly as before. Batching does not suffer: draws that are the same in everything else still merge into one call, because each instance carries its own set of lights. Order and blending of see-through things are not changed.

Large meshes

A surface made with CreateSurface, AddVertex and AddTriangle can hold more than 65535 vertices, and a triangle can use any of them. The original Blitz3D and Blitz3D_Soloud keep triangle corners as 16 bit numbers, so a surface with more vertices crashes in RenderWorld. Here the corners are 32 bit numbers, so CountVertices and CountTriangles count everything you added and every triangle is drawn.

A grid of 78000 vertices, red up to vertex 65535 and blue after it

Mip maps

Textures with flag 8 get a chain of mip maps and are sampled with trilinear filtering, which blends between two levels.

  • The levels are made by averaging 2 by 2 texels. Masked (flag 4) and alpha textures average their alpha as well, as the original did, which makes their edges soft from afar.
  • The levels of a texture that is drawn on (TextureBuffer) are made again before the texture is next used in a scene.
  • Levels stored in a block compressed DDS file are used instead of made ones.
  • The frames of a texture (LoadAnimTexture, CreateTexture with frames) are the layers of one image, and each has levels of its own, so levels never blend frames. A block compressed or deep picture loaded with LoadAnimTexture stays a sheet, and then they do.

Flag 8 alone does not use anisotropic filtering. The originals had no way to ask for it, but a sampler can (CreateSampler, SetSamplerAnisotropy and SetTextureSampler):

tex = LoadTexture("floor.png", 1 + 8)
sampler = CreateSampler()
SetSamplerAnisotropy sampler, 8
SetTextureSampler tex, sampler

See CreateSampler for the rest of the settings.

Home · Command Index


Getting started

Language

Tools


Language Features
BlitzBasic
Blitz3D
BlitzPlus
Differences

Clone this wiki locally