Colour Cube: Difference between revisions

From Burnout Wiki
Content added Content deleted
(Updated m_size description to reflect its known use.)
m (Changed ^3 to ³ to avoid confusion with bitwise XOR.)
 
(9 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{ParadiseResourceTypeInfobox
| 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.
ColourCube resources are used by both the [[EnvironmentSettings]] and [[PostFX]] to change the colour and tone of the world.


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'').
[[File:Paradise_ColourCubes.png|thumb|200px|ColourCubes used in 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.
A ColourCube is a set of 32 32x32 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 (i.e., the red filter when wrecking a vehicle in versions 1.0-1.3 of Burnout Paradise).


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.
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.


= Structures =
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.
=== rw::graphics::postfx::ColourCube ===

= Layout =
==== 32-bit ====
=== 32-bit ===
{| class="wikitable"
{| class="wikitable"
|-
! Offset !! Length !! Type !! Name !! Description !! Comments
! Offset !! Length !! Type !! Name !! Description !! Comments
|-
|-
| 0x0 || 0x4 || uint32_t || m_size || The number of textures and their length/width. || Used to calculate file size (m_size^3 * 3 + 16)
| 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. ||
| 0x4 || 0x4 || uint8_t* || m_pixels || Pointer to the texture data. ||
|}
|}

=== 64-bit ===
==== 64-bit ====
{| class="wikitable"
{| class="wikitable"
|-
! Offset !! Length !! Type !! Name !! Description !! Comments
! Offset !! Length !! Type !! Name !! Description !! Comments
|-
|-
| 0x0 || 0x4 || uint32_t || m_size || The number of textures and their length/width. || Used to calculate file size (m_size^3 * 3 + 16)
| 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. ||
| 0x8 || 0x8 || uint8_t* || m_pixels || Pointer to the texture data. ||
Line 30: Line 40:


= 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].
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 ==
== 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 NFS:HP 16*16*16 cubes.
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).
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"
{| class="wikitable"
|-
! x !! y !! z !! offset (m_size = 16)
! x !! y !! z !! offset (m_size = 16)
|- style="vertical-align:top;"
|- style="vertical-align:top;"
| <syntaxhighlight>xxxx
| <pre>xxxx
3210</syntaxhighlight> || <syntaxhighlight>yyyy
3210</pre> || <pre>yyyy
3210</syntaxhighlight> || <syntaxhighlight>zzzz
3210</pre> || <pre>zzzz
3210</syntaxhighlight> || <syntaxhighlight>o0=x0
3210</pre> || <pre>o0=x0
o1=x1
o1=x1
o2=y0
o2=y0
Line 55: Line 64:
o9=z1
o9=z1
o10=z2
o10=z2
o11=z3</syntaxhighlight>
o11=z3</pre>
|}
|}


{| class="wikitable"
{| class="wikitable"
|-
! x !! y !! z !! offset (m_size = 32)
! x !! y !! z !! offset (m_size = 32)
|- style="vertical-align:top;"
|- style="vertical-align:top;"
| <syntaxhighlight>xxxxx
| <pre>xxxxx
43210</syntaxhighlight> || <syntaxhighlight>yyyyy
43210</pre> || <pre>yyyyy
43210</syntaxhighlight> || <syntaxhighlight>zzzzz
43210</pre> || <pre>zzzzz
43210</syntaxhighlight> || <syntaxhighlight>o0=x0
43210</pre> || <pre>o0=x0
o1=x1
o1=x1
o2=y0
o2=y0
Line 79: Line 87:
o12=z2
o12=z2
o13=z3
o13=z3
o14=z4</syntaxhighlight>
o14=z4</pre>
|}
|}



Latest revision as of 09:03, 1 November 2023

ColourCube
aka RwColourCube

ColourCubes used in Burnout Paradise.
Resource names Unknown
Type ID 0x2B
Category Generic
Memory
distribution
Main Memory only
Imports Unknown
Imported by Environment Keyframe
Editor
available?
No

ColourCube resources are used by both the EnvironmentSettings and PostFX to change the colour and tone of the world.

A ColourCube is a set of textures forming a 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 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 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.

Structures

rw::graphics::postfx::ColourCube

32-bit

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_size3 * 3 + 16)
0x4 0x4 uint8_t* m_pixels Pointer to the texture data.

64-bit

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_size3 * 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 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).

x y z offset (m_size = 16)
xxxx
3210
yyyy
3210
zzzz
3210
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
x y z offset (m_size = 32)
xxxxx
43210
yyyyy
43210
zzzzz
43210
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

Example Ruby implementation:

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
# ...