Colour Cube: Difference between revisions

m
Changed ^3 to ³ to avoid confusion with bitwise XOR.
(Created page with "A Colourcube resource is used by both the Environmentsettings and PostFX to change the colour and tone of the world. The colourcube is a 1024x32 CLUT which is usually colour corrected to give a different art style to the game at a given time (i.e the red filter when wrecking a vehicle in versions 1.0-1.3 of Burnout Paradise) Some time after the February 22, 2007 build of Paradise, colourcubes were added to the Environmentsetting...")
 
m (Changed ^3 to ³ to avoid confusion with bitwise XOR.)
 
(23 intermediate revisions by 5 users not shown)
Line 1:
{{ParadiseResourceTypeInfobox
A Colourcube resource is used by both the [[Environmentsettings]] and [[PostFX]] to change the colour and tone of the world.
| name = ColourCube
| othernames = RwColourCube
| example = [[File:Paradise_ColourCubes.png|frameless|200px]]<br />ColourCubes used in Burnout Paradise.
| id = 0x2B
| category = Generic
| memdist = Main Memory only
| importedby = [[Environment Keyframe]]
}}
 
ColourCube resources are used by both the [[EnvironmentSettings]] and [[PostFX]] to change the colour and tone of the world.
The colourcube is a 1024x32 CLUT which is usually colour corrected to give a different art style to the game at a given time (i.e the red filter when wrecking a vehicle in versions 1.0-1.3 of Burnout Paradise)
 
A ColourCube is a set of textures forming a [https://en.wikipedia.org/wiki/Palette_(computing) CLUT], which is usually colour corrected to give a different art style to the game at a given time (e.g., the red filter when wrecking a vehicle in versions 1.0-1.3 of ''Burnout Paradise'').
Some time after the [[Burnout_5_(2007-02-22_build)|February 22, 2007]] build of Paradise, colourcubes were added to the Environmentsettings folder and were used specifically to give the game a unique art style.
 
Some time after the [[Burnout 5 (2007-02-22 build)|February 22, 2007]] build of ''Paradise'', ColourCubes were added to the EnvironmentSettings folder and were used specifically to give the game a unique art style.
In the 1.4 update to Burnout Paradise, the colourcube was changed to a standard RGB CLUT, possibly due to the extended timecycle conflicting with the colourcube's art style.
 
In the 1.4 update to ''Burnout Paradise'', the ColourCubes were changed to a standard CLUT, possibly due to the extended time cycle conflicting with the ColourCube's art style. In the 1.6 update, these were again updated to use a default RGB CLUT.
[[File:9D EC 31 13.png|thumb|An RGB CLUT, used as a Colourcube in all known versions of Burnout Paradise]]
 
= Structures =
=== rw::graphics::postfx::ColourCube ===
==== 32-bit ====
{| class="wikitable"
! Offset !! Length !! Type !! Name !! Description !! Comments
|-
| 0x0 || 0x4 || uint32_t || m_size || The number of textures and their width/height. || Used to calculate file size (m_size<sup><small>3</small></sup> * 3 + 16)
|-
| 0x4 || 0x4 || uint8_t* || m_pixels || Pointer to the texture data. ||
|}
 
==== 64-bit ====
{| class="wikitable"
! Offset !! Length !! Type !! Name !! Description !! Comments
|-
| 0x0 || 0x4 || uint32_t || m_size || The number of textures and their width/height. || Used to calculate file size (m_size<sup><small>3</small></sup> * 3 + 16)
|-
| 0x4 || 0x4 || || Padding || ||
|-
| 0x8 || 0x8 || uint8_t* || m_pixels || Pointer to the texture data. ||
|}
 
= Data =
In ''Burnout Paradise: The Ultimate Box'' on PC and ''Burnout Paradise Remastered'' on PC and PS4, data is in a standard RGB24 format (that is, each pixel takes up 3 bytes, one for each color). Textures in the PS3, Xbox 360, and Switch versions of the game are also RGB24, but swizzled. There is a functional implementation of an Xbox 360 to PC texture converter [https://github.com/burninrubber0/ColourCube_Converter on GitHub].
 
== Xbox 360 Swizzle Algorithm ==
The following algorithm assumes that the data is stored as a cube of size m_size*m_size*m_size pixels, accessed according to a certain algorithm. The algorithm is different for ''Burnout Paradise'' 32*32*32 cubes and ''Need for Speed: Hot Pursuit'' 16*16*16 cubes.
 
To find the 3 bytes (R, G and B) of pixel data for position (x,y,z) in the PC m_pixels data, 3 bytes (R, G and B) can be read from the Xbox 360 m_pixels data at the offset calculated as follows where x, y and z are represented as a number of bits, x0 to x4, y0 to y4 and z0 to z4 (all values between 0 and m_size - 1).
 
{| class="wikitable"
! x !! y !! z !! offset (m_size = 16)
|- style="vertical-align:top;"
| <pre>xxxx
3210</pre> || <pre>yyyy
3210</pre> || <pre>zzzz
3210</pre> || <pre>o0=x0
o1=x1
o2=y0
o3=x2
o4=x3
o5=y1
o6=y2
o7=z0
o8=y3^z2
o9=z1
o10=z2
o11=z3</pre>
|}
 
{| class="wikitable"
! x !! y !! z !! offset (m_size = 32)
|- style="vertical-align:top;"
| <pre>xxxxx
43210</pre> || <pre>yyyyy
43210</pre> || <pre>zzzzz
43210</pre> || <pre>o0=x0
o1=x1
o2=y0
o3=x2
o4=x3
o5=x4^y3^z2
o6=y1
o7=y2
o8=z0
o9=y3^z2
o10=z1
o11=y4
o12=z2
o13=z3
o14=z4</pre>
|}
 
Example Ruby implementation:
<syntaxhighlight lang="ruby" line>
class Fixnum
# calculates the number of bytes
def pixels
self * 3
end
end
 
# calculate offset, in pixels, of where to find the (x,y,z) pixel in the Xbox 360 data
# pixel offset in PC file is m_size * m_size * z + m_size * y + x
def calc_offset(m_size, x, y, z)
case m_size
when 16
calc_offset16(x, y, z)
when 32
calc_offset32(x, y, z)
else
raise "Unsupported m_size: #{m_size}"
end
end
 
def calc_offset16(x, y, z)
x0 = (x >> 0) & 0b1
x1 = (x >> 1) & 0b1
x2 = (x >> 2) & 0b1
x3 = (x >> 3) & 0b1
y0 = (y >> 0) & 0b1
y1 = (y >> 1) & 0b1
y2 = (y >> 2) & 0b1
y3 = (y >> 3) & 0b1
z0 = (z >> 0) & 0b1
z1 = (z >> 1) & 0b1
z2 = (z >> 2) & 0b1
z3 = (z >> 3) & 0b1
 
o=(z3<<11)|
(z2<<10)|
(z1<<9)|
((y3<<8)^(z2<<8))|
(z0<<7)|
(y2<<6)|
(y1<<5)|
(x3<<4)|
(x2<<3)|
(y0<<2)|
(x1<<1)|
(x0<<0)
end
 
def calc_offset32(x, y, z)
x0 = (x >> 0) & 0b1
x1 = (x >> 1) & 0b1
x2 = (x >> 2) & 0b1
x3 = (x >> 3) & 0b1
x4 = (x >> 4) & 0b1
y0 = (y >> 0) & 0b1
y1 = (y >> 1) & 0b1
y2 = (y >> 2) & 0b1
y3 = (y >> 3) & 0b1
y4 = (y >> 4) & 0b1
z0 = (z >> 0) & 0b1
z1 = (z >> 1) & 0b1
z2 = (z >> 2) & 0b1
z3 = (z >> 3) & 0b1
z4 = (z >> 4) & 0b1
 
o=(z4<<14)|
(z3<<13)|
(z2<<12)|
(y4<<11)|
(z1<<10)|
((z2<<9)^(y3<<9))|
(z0<<8)|
(y2<<7)|
(y1<<6)|
((z2<<5)^(y3<<5)^(x4<<5))|
(x3<<4)|
(x2<<3)|
(y0<<2)|
(x1<<1)|
(x0<<0)
end
 
# read m_size and m_pixels data from Xbox 360 file
# ...
 
# now, convert the m_pixels data
data="".b
m_size.times do |z|
m_size.times do |y|
m_size.times do |x|
offset = calc_offset(x, y, z)
pixel_data = m_pixels[offset.pixels...(offset + 1).pixels]
data << pixel_data
end
end
end
 
# write "converted to PC" data to file
# ...
‎</syntaxhighlight>