-
Notifications
You must be signed in to change notification settings - Fork 133
Graphics Synthesizer
The graphics chip for the PS2.
The GS was designed to draw 3D texture-mapped models pretty efficiently which has an effect on the methods of drawing 2D primitives.
This is a 12.4 fixed-point coordinate space for drawing primitives. The XY offset register sets the framebuffer to a specific set of coordinates in this space.
- X1,Y1
The topmost/leftmost pixel coordinates are always rounded up to the next whole pixel coordinate or unchanged if at a whole pixel coordinate. - X2,Y2
The bottommost/rightmost pixel coordinates are always rounded down to the last whole pixel coordinate they pass even if at a whole pixel coordinate. E.g. 32,32 is rounded down to 31,31
As you can see, it’s setup this way so that vertices don’t overlap each other when rendering 3D models.
Texture filtering and the level of detail setting has a great impact on the coordinates that will work for pixel-perfect mapping. The level of detail should be set so that the level of detail is at its greatest, level 0, to minimize filtering calculations. Filtering should be set to point sampling, which uses a simpler equation than bilinear filtering.
The GS can use STQ coordinates (0.0-1.0 full floating point) for perspective correct mapping or UV texel coordinates (12.4 fixed point) for direct texture mapping. I haven’t used STQ mapping all that much so I’ll explain the UV coordinate system.
These are texel coordinates, which are mapped to half-pixel boundaries. Texel 0 is at 0.5,0.5 which maps pixels 0 through 1 of the texture to the primitive.
Example:
These coordinates setup a 32×32 rectangle to be drawn at coordinate 0,0 to 31,31 with a 32×32 texture mapped from texel 0.5,0.5 (0-1) to 30.5,30.5 (pixels 30-31).
- X1,Y1 = 0.0f,0.0f
- X2,Y2 = 31.0625f,31.0625f
- U1,V1 = 0.5f,0.5f
- U2,V2 = 30.5f,30.5f
You can probably see the problem here. If X1,Y1 were even 0.0625f over the last whole pixel, it would jump to the next pixel, and X2,Y2 would be 31.125f,31.125f then you’d only have a 31 pixel primitive going from 1,1 to 31,31 as the top/left is rounded up but the bottom/right is rounded down.
Fixed Example:
These coordinates set up a 32×32 rectangle to be drawn at any coordinate while also accounting for rounding problems.
- X1,Y1 = X1 – 0.4375f,Y1 – 0.4375f
- X2,Y2 = X2 + 0.5625f,Y2 + 0.5625f
With these values, X1,Y1 will be forced to round down half a pixel and X2,Y2 will round up half a pixel.
1.0f,1.0f as the coordinates will set drawing from 1,1 to 32,32
- X1,Y1 = 0.5625f,0.5625f
- X2,Y2 = 32.5625f,32.5625f
1.4375f,1.4375f as the coordinates will set drawing from 1,1 to 32,32
- X1,Y1 = 1.0f,1.0f
- X2,Y2 = 33.0f,33.0f (rounded down to 32.0f,32.0f)
1.5f,1.5f as the coordinates will set drawing from 2,2 to 33,33
- X1,Y1 = 1.0625f,1.0625f
- X2,Y2 = 33.0625f,33.0625f
You can adjust rounding using 1/16th of a pixel decrements/increments to round at a specific partial value.