Jump to content

  • Log In with Google      Sign In   
  • Create Account

#Actuald k h

Posted 10 July 2012 - 05:44 AM

I'm working on a 3D space game that, for the enemy spaceships, uses sprites (pre-rendered from every angle) instead of models. All spaceships have 544 angles (32 angles of yaw, 17 of pitch), each individual sprite is 256x256. We used to just load in 544 single 256x256 texture files in the beginning - and on decent hardware that would take at the very least 30 seconds to load. When you have 10+ different spaceship classes in a mission, that made for absolutely unacceptable loading times. I then wrote a tool that would read in the 544 sprites and output 17 spritesheets for each ship (ie. one sheet for each pitch rotation), each spritesheet containing 32 256x256 sprites (all the yaws in the pitch of the spritesheet) - so 2048x1024. This reduced loading times down to 2-3 seconds per ship.

In a nutshell: how effective spritesheets are over individual sprites depends on your game, my game is probably one of the strongest cases you'll find, if you're talking about 16 8x8 sprites, however, it probably won't make that much sense for example. How large you can make your spritesheets depends on the hardware you're targeting, you mention 512x512, that's extremely conservative. If you're not aiming at supporting really old GPUs you can certainly go up to 4096x4096, I'd be willing to bet that all GPUs that came out like 6 years or earlier maybe(?) will support this texture size. And then there's even more to it, if you look at memory consumption, you need to consider using DXTn texture compression. This will also speed up loading times in case you're converting each loaded texture from their PNG or JPEG format to RGB(A) at the moment. Last but not least, make sure to use a vertex shader for selecting the portion of the spritesheet you actually want. Doing this on the CPU is a really bad idea these days, for obvious reasons.

Here's an example of a vertex shader that does this (HLSL):
[source lang="cpp"]float4x4 mat_worldviewproj;float4 rect;struct vs_input{ float4 position : POSITION; float2 uv : TEXCOORD0;};struct vs_output{ float4 position : POSITION; float2 uv : TEXCOORD0;};vs_output MyVertexShader ( vs_input input ){ vs_output output; // transform vertex into screen space for rendering output.position = mul ( float4 ( input.position.xyz, 1.0f ), mat_worldviewproj ); // uv atlas (u/v/w/h of sprite in sheet, all range 0..1) output.uv.x = ( input.uv.x * rect.z ) + rect.x; output.uv.y = ( input.uv.y * rect.w ) + rect.y; return output;}[/source]

Just feed it the vector4 "rect" with the top left corner coordinates as the first two elements and then the width and height of the portion you want from the spritesheet (all in range 0..1 - this way the size of your texture is irrelevant to the shader).

Gone on a bit of a tangent there, hope this helps you in some way!

#4d k h

Posted 10 July 2012 - 04:46 AM

I'm working on a 3D space game that, for the enemy spaceships, uses sprites (pre-rendered from every angle) instead of models. All spaceships have 544 angles (32 angles of yaw, 17 of pitch), each individual sprite is 256x256. We used to just load in 544 single 256x256 texture files in the beginning - and on decent hardware that would take at the very least 30 seconds to load. When you have 10+ different spaceship classes in a mission, that made for absolutely unacceptable loading times. I then wrote a tool that would read in the 544 sprites and output 17 spritesheets for each ship (ie. one sheet for each pitch rotation), each spritesheet containing 32 256x256 sprites (all the yaws in the pitch of the spritesheet) - so 2048x1024. This reduced loading times down to 2-3 seconds per ship.

In a nutshell: how effective spritesheets are over individual sprites depends on your game, my game is probably one of the strongest cases you'll find, if you're talking about 16 8x8 sprites, however, it probably won't make that much sense for example. How large you can make your spritesheets depends on the hardware you're targeting, you mention 512x512, that's extremely conservative. If you're not aiming at supporting really old GPUs you can certainly go up to 4096x4096, I'd be willing to bet that all GPUs that came out like 6 years or earlier maybe(?) will support this texture size. And then there's even more to it, if you look at memory consumption, you need to consider using DXTn texture compression. This will also speed up loading times in case you're converting each loaded texture from their PNG or JPEG format to RGB(A) at the moment. Last but not least, make sure to use a vertex shader for selecting the portion of the spritesheet you actually want. Doing this on the CPU is a really bad idea these days, for obvious reasons.

Here's an example of a vertex shader that does this:
[source lang="cpp"]float4x4 mat_worldviewproj;float4 rect;struct vs_input{ float4 position : POSITION; float2 uv : TEXCOORD0;};struct vs_output{ float4 position : POSITION; float2 uv : TEXCOORD0;};vs_output MyVertexShader ( vs_input input ){ vs_output output; // transform vertex into screen space for rendering output.position = mul ( float4 ( input.position.xyz, 1.0f ), mat_worldviewproj ); // uv atlas (u/v/w/h of sprite in sheet, all range 0..1) output.uv.x = ( input.uv.x * rect.z ) + rect.x; output.uv.y = ( input.uv.y * rect.w ) + rect.y; return output;}[/source]

Just feed it the vector4 "rect" with the top left corner coordinates as the first two elements and then the width and height of the portion you want from the spritesheet (all in range 0..1 - this way the size of your texture is irrelevant to the shader).

Gone on a bit of a tangent there, hope this helps you in some way!

#3d k h

Posted 10 July 2012 - 04:45 AM

I'm working on a 3D space game that, for the enemy spaceships, uses sprites (pre-rendered from every angle) instead of models. All spaceships have 544 angles (32 angles of yaw, 17 of pitch), each individual sprite is 256x256. We used to just load in 544 single 256x256 texture files in the beginning - and on decent hardware that would take at the very least 30 seconds to load. When you have 10+ different spaceship classes in a mission, that made for absolutely unacceptable loading times. I then wrote a tool that would read in the 544 sprites and output 17 spritesheets for each ship (ie. one sheet for each pitch rotation), each spritesheet containing 32 256x256 sprites (all the yaws in the pitch of the spritesheet) - so 2048x1024. This reduced loading times down to 2-3 seconds per ship.

In a nutshell: how effective spritesheets are over individual sprites depends on your game, my game is probably one of the strongest cases you'll find, if you're talking about 16 8x8 sprites, however, it probably won't make that much sense for example. How large you can make your spritesheets depends on the hardware you're targeting, you mention 512x512, that's extremely conservative. If you're not aiming at supporting really old GPUs you can certainly go up to 4096x4096, I'd be willing to bet that all GPUs that came out like 6 years or earlier maybe(?) will support this texture size. And then there's even more to it, if you look at memory consumption, you need to consider using DXTn texture compression. This will also speed up loading times in case you're converting each loaded texture from their PNG or JPEG format to RGB(A) at the moment. Last but not least, make sure to use a vertex shader for selecting the portion of the spritesheet you actually want. Doing this on the CPU is a really bad idea these days, for obvious reasons.

Here's an example of a vertex shader that does this:
[source lang="cpp"]float4x4 mat_worldviewproj;float4 rect;struct vs_input{ float4 position : POSITION; float2 uv : TEXCOORD0;};struct vs_output{ float4 position : POSITION; float2 uv : TEXCOORD0;};vs_output MyVertexShader ( vs_input input ){ vs_output output; // transform vertex into screen space for rendering output.position = mul ( float4 ( input.position.xyz, 1.0f ), mat_worldviewproj ); // uv atlas (u/v/w/h of sprite in sheet, all range 0..1) output.uv.x = ( input.uv.x * rect.z ) + rect.x; output.uv.y = ( input.uv.y * rect.w ) + rect.y; return output;}[/source]

Just feed it the vector4 "rect" with the top left corner coordinates as the first two elements and then the width and height of the portion you want from the spritesheet (all in range 0..1 - this way the size of your texture is irrelevant).

Gone on a bit of a tangent there, hope this helps you in some way!

#2d k h

Posted 10 July 2012 - 04:45 AM

I'm working on a 3D space game that, for the enemy spaceships, uses sprites (pre-rendered from every angle) instead of models. All spaceships have 544 angles (32 angles of yaw, 17 of pitch), each individual sprite is 256x256. We used to just load in 544 single 256x256 texture files in the beginning - and on decent hardware that would take at the very least 30 seconds to load. When you have 10+ different spaceship classes in a mission, that made for absolutely unacceptable loading times. I then wrote a tool that would read in the 544 sprites and output 17 spritesheets for each ship (ie. one sheet for each pitch rotation), each spritesheet containing 32 256x256 sprites (all the yaws in the pitch of the spritesheet) - so 2048x1024. This reduced loading times down to 2-3 seconds per ship.

In a nutshell: how effective spritesheets are over individual sprites depends on your game, my game is probably one of the strongest cases you'll find, if you're talking about 16 8x8 sprites, however, it probably won't make that much sense for example. How large you can make your spritesheets depends on the hardware you're targeting, you mention 512x512, that's extremely conservative. If you're not aiming at supporting really old GPUs you can certainly go up to 4096x4096, I'd be willing to bet that all GPUs that came out like 6 years or earlier maybe(?) will support 4096x4096. And then there's even more to it, if you look at memory consumption, you need to consider using DXTn texture compression. This will also speed up loading times in case you're converting each loaded texture from their PNG or JPEG format to RGB(A). Last but not least, make sure to use a vertex shader for selecting the portion of the spritesheet you actually want. Doing this on the CPU is a really bad idea these days, for obvious reasons.

Here's an example of a vertex shader that does this:
[source lang="cpp"]float4x4 mat_worldviewproj;float4 rect;struct vs_input{ float4 position : POSITION; float2 uv : TEXCOORD0;};struct vs_output{ float4 position : POSITION; float2 uv : TEXCOORD0;};vs_output MyVertexShader ( vs_input input ){ vs_output output; // transform vertex into screen space for rendering output.position = mul ( float4 ( input.position.xyz, 1.0f ), mat_worldviewproj ); // uv atlas (u/v/w/h of sprite in sheet, all range 0..1) output.uv.x = ( input.uv.x * rect.z ) + rect.x; output.uv.y = ( input.uv.y * rect.w ) + rect.y; return output;}[/source]

Just feed it the vector4 "rect" with the top left corner coordinates as the first two elements and then the width and height of the portion you want from the spritesheet (all in range 0..1 - this way the size of your texture is irrelevant).

Gone on a bit of a tangent there, hope this helps you in some way!

#1d k h

Posted 10 July 2012 - 04:43 AM

I'm working on a 3D space game that, for the enemy spaceships, uses sprites (pre-rendered from every angle) instead of models. All spaceships have 544 angles (32 angles of yaw, 17 of pitch), each individual sprite is 256x256. We used to just load in 544 single 256x256 texture files in the beginning - and on decent hardware that would take at the very least 30 seconds to load. When you have 10+ different spaceship classes in a mission, that made for absolutely unacceptable loading times. I then wrote a tool that would read in the 544 sprites and output 17 spritesheets for each ship (ie. one sheet for each pitch rotation), each spritesheet containing 32 256x256 sprites (all the yaws in the pitch of the spritesheet) - so 2048x1024. This reduced loading times down to 2-3 seconds per ship.

In a nutshell: how effective spritesheets are over individual sprites depends on your game, my game is probably one of the strongest cases you'll find, if you're talking about 16 8x8 sprites, however, it probably won't make that much sense for example. How large you can make your spritesheets depends on the hardware you're targeting, you mention 512x512, that's extremely conservative. If you're not aiming at supporting really old GPUs you can certainly go up to 4096x4096, I'd be willing to bet that all semi-recent GPUs (6 years or younger) will support 4096x4096. And then there's even more to it, if you look at memory consumption, you need to consider using DXTn texture compression. This will also speed up loading times in case you're converting each loaded texture from their PNG or JPEG format to RGB(A). Last but not least, make sure to use a vertex shader for selecting the portion of the spritesheet you actually want. Doing this on the CPU is a really bad idea these days, for obvious reasons.

Here's an example of a vertex shader that does this:
[source lang="cpp"]float4x4 mat_worldviewproj;float4 rect;struct vs_input{ float4 position : POSITION; float2 uv : TEXCOORD0;};struct vs_output{ float4 position : POSITION; float2 uv : TEXCOORD0;};vs_output MyVertexShader ( vs_input input ){ vs_output output; // transform vertex into screen space for rendering output.position = mul ( float4 ( input.position.xyz, 1.0f ), mat_worldviewproj ); // uv atlas (u/v/w/h of sprite in sheet, all range 0..1) output.uv.x = ( input.uv.x * rect.z ) + rect.x; output.uv.y = ( input.uv.y * rect.w ) + rect.y; return output;}[/source]

Just feed it the vector4 "rect" with the top left corner coordinates as the first two elements and then the width and height of the portion you want from the spritesheet (all in range 0..1 - this way the size of your texture is irrelevant).

Gone on a bit of a tangent there, hope this helps you in some way!

PARTNERS