Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Baldbeard
Mar 26, 2011

Okay, I have another question. I've hit a serious roadblock and I've wasted hours away on it now.

I made it so my 2D game levels contain the player character. To center the "camera", I made it so the level moves in the opposite direction of the character (and takes the character with it, since it is inside). Everything stays centered and peachy. Well now I want boundaries so the camera won't pan when I'm near the edge of a level. Otherwise the character is going to get half a screen of nothing(or padding I have to deal with) when they are on a level's edge.

So I made it so panning only happens when the character is within a boundary I set. After testing it, I noticed that when the character crosses a boundary and the panning starts, I lose a step in the opposite direction. So let's say panning starts when the character's X position is between 100 and 900. When I cross from 100 to 101, the map moves from 0 to -1 to compensate. So the end result is the character's x is back at 100 but now the map is -1;

What the gently caress am I doing wrong? Should I not have the character in the level, but rather have both the level and the character in a different container altogether and move that? Or move the level in the opposite direction and not move the character when I want to pan, and switch to moving the character and not the level when I don't want to pan?

Baldbeard fucked around with this message at 03:46 on May 28, 2013

Adbot
ADBOT LOVES YOU

KoRMaK
Jul 31, 2012



I have had the exact same issue. I think it's a matter of using >= or > in your screen gutter detection.

Coldrice
Jan 20, 2006


Whew! I spent the week with c# / unity / futile. I spent the last 2 days working on making tile maps work in futile. I feel really pleased! The results aren't great, but it's results! Really I'm shocked by how much quicker I'm picking up c# then I did obj-c.

;

There are gaps in my tiles for some reason which I'll figure out later, but they show up! I'm hoping I can avoid buying texturePacker.

Coldrice fucked around with this message at 08:15 on Dec 17, 2013

seiken
Feb 7, 2005

hah ha ha

Baldbeard posted:

When I cross from 100 to 101, the map moves from 0 to -1 to compensate. So the end result is the character's x is back at 100 but now the map is -1;

I don't get it. Isn't this exactly what you wanted to happen?

Regardless of that, moving the level as a proxy for a camera is kind of confusing. If possible I'd advise storing a separate camera position and when you draw the level, offset everything by the negative of the camera position. Then it's pretty trivial to do boundaries, just set the camera position to min(boundary_max, max(boundary_min, player_position)) every frame.

superh
Oct 10, 2007

Touching every treasure

Baldbeard posted:

Camera woes

seiken posted:

I don't get it. Isn't this exactly what you wanted to happen?

Regardless of that, moving the level as a proxy for a camera is kind of confusing. If possible I'd advise storing a separate camera position and when you draw the level, offset everything by the negative of the camera position. Then it's pretty trivial to do boundaries, just set the camera position to min(boundary_max, max(boundary_min, player_position)) every frame.

Yeah do this, exactly. Make a camera variable (just a point) and render the whole level off it. Set it to the player position, but clamp it to half the screen width of the outer boundary.



Coldrice posted:

Whew! I spent the week with c# / unity / futile. I spent the last 2 days working on making tile maps work in futile. I feel really pleased! The results aren't great, but it's results! Really I'm shocked by how much quicker I'm picking up c# then I did obj-c.

;

There are gaps in my tiles for some reason which I'll figure out later, but they show up! I actually ended up writing a c# program to parse data and output the information necessary for futile to accept my simple spritesheet for tiles, so I'm hoping it'll allow me to avoid buying texturePacker. I even made a video of my little application :) http://youtu.be/_CpjS0_k1u8

I think you're having the same problem someone else had just a little bit earlier in the thread - make sure your textures are set to point filtering for pixel art instead of bilinear. It's bleeding. Looks awesome though!


I've been playing with futile over the long weekend too, porting an olllllld project from XNA. I'm coming from a flash / haxe background so a lot of the guts of OpenGL and 3d are a mystery to me, but I was wondering if anyone had any suggestion for per-pixel tinting of an image. I was jury rigging something horrific in XNA (each player character pixel was a separate tinted draw...) and I'd like to do something less terrible in unity.

Am I looking at shaders? Or is there an easy way to do some dynamic masking in unity?

TheresaJayne
Jul 1, 2011

Baldbeard posted:

Okay, I have another question. I've hit a serious roadblock and I've wasted hours away on it now.

I made it so my 2D game levels contain the player character. To center the "camera", I made it so the level moves in the opposite direction of the character (and takes the character with it, since it is inside). Everything stays centered and peachy. Well now I want boundaries so the camera won't pan when I'm near the edge of a level. Otherwise the character is going to get half a screen of nothing(or padding I have to deal with) when they are on a level's edge.

So I made it so panning only happens when the character is within a boundary I set. After testing it, I noticed that when the character crosses a boundary and the panning starts, I lose a step in the opposite direction. So let's say panning starts when the character's X position is between 100 and 900. When I cross from 100 to 101, the map moves from 0 to -1 to compensate. So the end result is the character's x is back at 100 but now the map is -1;

What the gently caress am I doing wrong? Should I not have the character in the level, but rather have both the level and the character in a different container altogether and move that? Or move the level in the opposite direction and not move the character when I want to pan, and switch to moving the character and not the level when I don't want to pan?

That sounds about right however i think what you need to do is when you move from 100 to 101 you move the level not the player.
or if it moves him back then its move player and level.

Baldbeard
Mar 26, 2011

TheresaJayne posted:

That sounds about right however i think what you need to do is when you move from 100 to 101 you move the level not the player.
or if it moves him back then its move player and level.

Yeah I had the character within the level, so both were being moved after the player moved independently, causing the player to move twice so to speak. I figured out a a formula that shows the loss caused by this, based on any level/character position, so I have it auto correcting itself.

Haha definitely jerry rigged, but I'm almost proud. I'll try the camera point variable suggestions for sure if this causes any more problems.

Im on actionscropt3 btw. So if I add the level to the stage based off of the camera/character position - won't i still have to move the level around to center the moving character in the viewable area?

I guess I don't quite understand the concept. How do I move the actual viewable canvas or stage or whatever? I assumed you had to move the objects in and out of a stationary stage view for a "camera effect".

Baldbeard fucked around with this message at 16:26 on May 28, 2013

KoRMaK
Jul 31, 2012



Coldrice posted:

Whew! I spent the week with c# / unity / futile. I spent the last 2 days working on making tile maps work in futile. I feel really pleased! The results aren't great, but it's results! Really I'm shocked by how much quicker I'm picking up c# then I did obj-c.

;

There are gaps in my tiles for some reason which I'll figure out later, but they show up! I actually ended up writing a c# program to parse data and output the information necessary for futile to accept my simple spritesheet for tiles, so I'm hoping it'll allow me to avoid buying texturePacker. I even made a video of my little application :) http://youtu.be/_CpjS0_k1u8
Hah I saw you posting in the pixel thread. It's neat to get another side of the project. I'm always caught off guard when I see Unity used for 2d and I ask "why not HTML5" then i realize Unity has cross platform capabilities and allows for a standalone app.

I only use unity for 3d but that will probably change soon.

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.

KoRMaK posted:

I only use unity for 3d but that will probably change soon.

I dunno, I think there's a reason most everybody uses unity for 3D, it was designed that way. Sure you can use it for 2D but its such a huge library of crap you won't ever need that's mixed in with your stuff necessarily, that's not ideal. Performance may take a hit too from unnecessary overhead.

There's lots of C# and Java libraries and engines you can use that can compile to a standalone app. I guess if cross compatibility is really huge for you though, then its hard to beat Unity.

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!

KoRMaK posted:

I'm always caught off guard when I see Unity used for 2d and I ask "why not HTML5"
Probably because using HTML5 implies using javascript. That's a good enough reason for me.

SupSuper
Apr 8, 2009

At the Heart of the city is an Alien horror, so vile and so powerful that not even death can claim it.

Baldbeard posted:

Yeah I had the character within the level, so both were being moved after the player moved independently, causing the player to move twice so to speak. I figured out a a formula that shows the loss caused by this, based on any level/character position, so I have it auto correcting itself.

Haha definitely jerry rigged, but I'm almost proud. I'll try the camera point variable suggestions for sure if this causes any more problems.

Im on actionscropt3 btw. So if I add the level to the stage based off of the camera/character position - won't i still have to move the level around to center the moving character in the viewable area?

I guess I don't quite understand the concept. How do I move the actual viewable canvas or stage or whatever? I assumed you had to move the objects in and out of a stationary stage view for a "camera effect".
The net effect is the same, (you can't actually move the screen, just what you see on it), but using a "camera point" as a referential makes it much simpler to manage. Then you just have to change the "camera point" when the player moves and position your objects relative to it, instead of always changing all your object positions directly with the player movement and hope it all matches up.

seiken
Feb 7, 2005

hah ha ha

SupSuper posted:

The net effect is the same, (you can't actually move the screen, just what you see on it), but using a "camera point" as a referential makes it much simpler to manage. Then you just have to change the "camera point" when the player moves and position your objects relative to it, instead of always changing all your object positions directly with the player movement and hope it all matches up.

Yeah. The main point is you don't actually move the objects, you just offset them when you draw them only. I don't know what libraries or whatever you're using but instead of moving the objects and doing draw(object, position) you move the camera and do draw(object, position - camera).

Coldrice
Jan 20, 2006


KoRMaK posted:

Hah I saw you posting in the pixel thread. It's neat to get another side of the project. I'm always caught off guard when I see Unity used for 2d and I ask "why not HTML5" then i realize Unity has cross platform capabilities and allows for a standalone app.

Not only that, but I DO want to move towards 3d games later on. Unity/Futile/C# is way different that obj-c/Xcode. I figured why not do this project in Unity, despite its challenges, so that when I do move towards 3d gaming I'm a little more prepared.

superh
Oct 10, 2007

Touching every treasure

Baldbeard posted:

Yeah I had the character within the level, so both were being moved after the player moved independently, causing the player to move twice so to speak. I figured out a a formula that shows the loss caused by this, based on any level/character position, so I have it auto correcting itself.

Haha definitely jerry rigged, but I'm almost proud. I'll try the camera point variable suggestions for sure if this causes any more problems.

Im on actionscropt3 btw. So if I add the level to the stage based off of the camera/character position - won't i still have to move the level around to center the moving character in the viewable area?

I guess I don't quite understand the concept. How do I move the actual viewable canvas or stage or whatever? I assumed you had to move the objects in and out of a stationary stage view for a "camera effect".

This means that you will have to 2 stage your rendering process in AS3. Instead of setting thing's x and y and trusting that, you only use that as it's screen space position, and you give each object a world space position variable. Then, you run a render(camera) function on each of your objects which sets their screen space position ( spite x and y ) to the world space position minus the camera position.

Then you can just move the camera and pan around, set it to the player's position or something else, it won't matter. Easy! Freedom! You'll love it! :D

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!
I should probably refactor this:
code:
Dictionary<LayerType, Dictionary<int, Dictionary<Matrix4, Dictionary<BlendingMode, Dictionary<Texture, List<RenderItem>>>>>>
:)

Baldbeard
Mar 26, 2011

superh posted:

This means that you will have to 2 stage your rendering process in AS3. Instead of setting thing's x and y and trusting that, you only use that as it's screen space position, and you give each object a world space position variable. Then, you run a render(camera) function on each of your objects which sets their screen space position ( spite x and y ) to the world space position minus the camera position.

Then you can just move the camera and pan around, set it to the player's position or something else, it won't matter. Easy! Freedom! You'll love it! :D

Yeah, that definitely sounds boss. I think I understand the basic concept now, but I'm not sure how I would go about actually implementing it. World space vs screen space + the camera position is a little much for my feeble brain right now. I would probably need to see an actual example to fill in the blanks. All in due time I guess. I really appreciate you guys taking the time to explain this stuff to me. And sorry for noobing up the thread.

If anyone's interested though, I figured out a seemingly solid fix for the "moving the level in the opposite direction" method. The problem is that the alignment can get out of whack when you cross whatever boundaries you set for panning to start/stop. So first I figured out a formula that stores whatever current panning is taking place considering your character is inside the level object.

//h_buffer = 1/2 stage width
h_pan = level.x -((player.x - h_buffer) * -1);

Then all I had to do was add if statements to only allow the level to move when the panning variable was correct.

if (left == true){
if(h_pan <= 0)
level.x += walk_speed;
}

if (right == true) {
if(h_pan >=0)
parent.x -= walk_speed;
}
Been testing it for the last 45 minutes. Seems to work fine.

Baldbeard fucked around with this message at 01:20 on May 29, 2013

superh
Oct 10, 2007

Touching every treasure

Baldbeard posted:

Yeah, that definitely sounds boss. I think I understand the basic concept now, but I'm not sure how I would go about actually implementing it. World space vs screen space + the camera position is a little much for my feeble brain right now. I would probably need to see an actual example to fill in the blanks. All in due time I guess. I really appreciate you guys taking the time to explain this stuff to me. And sorry for noobing up the thread.

No problem! The camera is definitely a weird thing to wrap your head around, at first. Pseudo-code, incoming!

So right now you're probably moving things around by stuff like:

_player.x += 10;
_player.y -= 10;

What you're really doing here is controlling both their screen position and their world position, which is not going to be accurate when you get beyond a single screen's worth of content (as I'm sure you're noticing, when you have to offset all the world positions as you move.)

What you should do, in each of your world elements, or a base class for all the things in your world, is separate the two concepts into screen position (the x and the y on the object, basically what Flash is using to render the object) and the world position - it's position in the game world relative to all the other objects.

So everything gets a Point - for this demonstration I'll call it "worldPos" to keep this information. You will use this Point instead of x and y for almost all the things you're using x and y for now.

Now you need another Point to act as the "camera", which you can use to do some math to figure out the screen position of the objects from their world position.

So to get the two to interact, put a function called something like "render" on the base class of all the objects in the world.

code:
public function render( camera:Point ) : void {
	this.x = worldPos.x - camera.x;
	this.y = worldPos.y - camera.y;
}
That will render the objects in the world around your camera! However there is one more thing you'll probably want, to make it a little more usable, since that formula actually bases your camera around 0,0, or the top left corner of the screen, which is not very intuitive. We need to add an offset to the camera. So when you first set it's position, put it at the middle of the screen - camera = new Point(stageWidth/2,stageHeight/2) - and then add that amount to the formula above in the render. (I just store them as static variables in another class so anything that needs them can access them from anywhere.)

That looks like this :
code:
public function render( camera:Point ) : void {
	this.x = worldPos.x - camera.x + stageWidth/2; 
	this.y = worldPos.y - camera.y + stageHeight/2;
	//Replace stageWidth/2 and stageHeight/2 with a static variable somewhere else to keep everything the same if your screen size changes
}
To pan around, simply change the camera Point's x and y! Do something like this, as you move your player around by changing it's worldPos:

code:
// Move the player however you want
if ( player_move_right ) {
	player.worldPos.x += 10;
}

// Snip

// Focus the camera on the player
camera.x = player.x;
camera.y = player.y;

// Cap the camera to it's bounds
if ( camera.x > cameraRightEdge ) {
	camera.x = cameraRightEdge;
}
// And all the other directions, of course!

// Now that the camera is set, you can safely "render" the world off it!
for ( int tI = 0; tI<_worldObjects.length; tI++ ) {
	_worldObjects[tI].render(camera);
}
Ta da! Now everything's rendering off the camera, which is centered on your screen. You can even pan over to another object by setting the camera's x and y to some other location independent of the player.

So that's a lot of stuff! But even if you don't fully understand it, try implementing that and playing around with it to see what you get. The net result will be the same and once you have it in place, it will be easier to conceptualize spatial movements and relationships, when the world stays constant and the player is moving within it.

Hope some of that helps!

superh fucked around with this message at 01:56 on May 29, 2013

KoRMaK
Jul 31, 2012



Here's my AS3 screen follower. Alt-click lets you drop "mob spawners." It sounds very similiar to what you are doing Baldbeard. I'm using Actionscript Physics Engine (APE) to handle the movement and collision detection. Sometimes I control player input manually, but in this example I let the inertia from APE handle it.

http://liquid-software.com/blog/as3-freeroam/

Thhis next example demonstrates the same engine but with side-scroller-esque input (no interia).
http://liquid-software.com/blog/a-nobel-quest/

Unormal
Nov 16, 2004

Mod sass? This evening?! But the cakes aren't ready! THE CAKES!
Fun Shoe

Orzo posted:

I should probably refactor this:
code:
Dictionary<LayerType, Dictionary<int, Dictionary<Matrix4, Dictionary<BlendingMode, Dictionary<Texture, List<RenderItem>>>>>>
:)

I see no problems here. :colbert:

superh
Oct 10, 2007

Touching every treasure

Orzo posted:

I should probably refactor this:
code:
Dictionary<LayerType, Dictionary<int, Dictionary<Matrix4, Dictionary<BlendingMode, Dictionary<Texture, List<RenderItem>>>>>>
:)

Just wait until you have to port it to Haxe and you're only supposed to use strings as Dictionary keys... :suicide:

e: vvvv that is awesome.

superh fucked around with this message at 02:24 on May 29, 2013

seiken
Feb 7, 2005

hah ha ha
So, I added arbitrary rotation to my collision system and then implemented a daft thing in like 10 lines of code and here is a gif of it sorry it's like 30MB I should start using youtube

seiken fucked around with this message at 02:25 on May 29, 2013

devilmouse
Mar 26, 2004

It's just like real life.

superh posted:

Just wait until you have to port it to Haxe and you're only supposed to use strings as Dictionary keys... :suicide:

Haxe 3's Maps support "most" objects as keys! :eng101:

(The haxe 3 final just came out last week and it is pretty great. We've been using it since the betas back in the fall and I have mostly nothing but praise. Mostly.)

superh
Oct 10, 2007

Touching every treasure

devilmouse posted:

Haxe 3's Maps support "most" objects as keys! :eng101:

(The haxe 3 final just came out last week and it is pretty great. We've been using it since the betas back in the fall and I have mostly nothing but praise. Mostly.)

Haxe 3 posted:

As a bonus, maps allow element access with the Array operator:

var map = new Map();
map["foo"] = 9;
trace(map["foo"]); // 9
map["foo"] += 12;
trace(map["foo"]); // 21

Woo hoo! Yeah this looks awesome, once our libraries are up to date we'll be switching for sure! Although I'm not sold on -

"Haxe 3 posted:

// haxe 2
var property(getProperty, setProperty):Int;
function getProperty() return 1
function setProperty(i) return 1

// haxe 3
var property(get, set):Int;
function get_property() return 1;
function set_property(i) return 2;

I kinda like being able to name my getters and setters (not that I ever use anything but _getVariable and _setVariable anyway). If they're going to still use the variable(get,set) syntax why do we still have to define strict names? I like C#'s { get {} set {} }.

Coldrice
Jan 20, 2006


Fixed the tile gaps in unity! adjusted the UV a little, and then set the texture mode thing to point. Wee!

devilmouse
Mar 26, 2004

It's just like real life.

superh posted:

I kinda like being able to name my getters and setters (not that I ever use anything but _getVariable and _setVariable anyway). If they're going to still use the variable(get,set) syntax why do we still have to define strict names? I like C#'s { get {} set {} }.

Yeah, that was a slightly odd change, but like you said, they're all just named get_/set_ anyway, so it was a pretty minor change and I gladly sacrifice that in exchange for the new maps, generic functions, and array comprehensions.

SupSuper
Apr 8, 2009

At the Heart of the city is an Alien horror, so vile and so powerful that not even death can claim it.

Orzo posted:

I should probably refactor this:
code:
Dictionary<LayerType, Dictionary<int, Dictionary<Matrix4, Dictionary<BlendingMode, Dictionary<Texture, List<RenderItem>>>>>>
:)

Pfffff in C++ you couldn't get away with such ugly code, you would actually be forced to clean up your act:
code:
Dictionary <LayerType, Dictionary <int, Dictionary <Matrix4, Dictionary <BlendingMode, Dictionary <Texture, List<RenderItem> > > > > >
Much better. :colbert:

RichardA
Sep 1, 2006
.
Dinosaur Gum

SupSuper posted:

Pfffff in C++ you couldn't get away with such ugly code, you would actually be forced to clean up your act:
In C++11 it works just fine with the >>'s. :colbert:

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

In C++11, you would use a std::tuple.

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!
The monstrosity of a variable that I posted isn't a tuple, though. It's a dictionary of dictionaries of dictionaries of dictionaries, etc). Unless I'm misunderstanding how C++ uses tuples, my understanding was that they were convenient container objects.

That Turkey Story
Mar 30, 2003

Orzo posted:

The monstrosity of a variable that I posted isn't a tuple, though. It's a dictionary of dictionaries of dictionaries of dictionaries, etc). Unless I'm misunderstanding how C++ uses tuples, my understanding was that they were convenient container objects.

Yeah, that's all that they are. I'm guessing he either means for you to make a single std::map with a key that is a tuple of all of your keys (which isn't really analogous to your situation, but might be all that you need) or he meant to say that you can use a variadic template so that you can do something like NDictionary<LayerType, int, Matrix4, BlendingMode, Texture, List<RenderItem>> to produce a dictionary of dictionaries of dictionaries of... without a ton of < and >.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

That Turkey Story posted:

Yeah, that's all that they are. I'm guessing he either means for you to make a single std::map with a key that is a tuple of all of your keys (which isn't really analogous to your situation, but might be all that you need) or he meant to say that you can use a variadic template so that you can do something like NDictionary<LayerType, int, Matrix4, BlendingMode, Texture, List<RenderItem>> to produce a dictionary of dictionaries of dictionaries of... without a ton of < and >.

Pretty much. :v:

seiken
Feb 7, 2005

hah ha ha
I really can't imagine what that dictionary of nonsense (including matrices!) could possibly be useful for.

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!
You're building your own engine for Super Fungus Adventure II, right? I'd be interested to hear how you solve the same problem with structure that looks nothing like that.

Just about every 2D graphics engine has some sort of layering and batching system to minimize state changes on the GPU. In my case, a state change is either (a) a texture change, (b) a blending mode change, or (c) a view transform change (I perform my view matrix calculations on the GPU and use a uniform for the matrix).

One way to accomplish this is to build a gigantic flat list of items to render and then sort/batch them after they've all been 'gathered'. For efficiency, I've chosen to instead insert them into the data structure as they're rendered.

When the data structure is complete, the renderer simply has to iterate over it and perform the necessary state changes at each level. Pseudocode, from memory:
code:
foreach(LayerType layerType in items.LayerTypes.Keys)
{
   gfx.SetLayerType(layerType); //might be a different shader or something
   var layersForThisLayerType = items[layerType];
   //Iterate over layers to ensure painters algorithm
   foreach(int layer in layersForthisLayerType.Keys)
   {
      var allBlendModes = layersForThisLayerType[layer];
      foreach(BlendMode blendMode in allBlendModes.Keys)
      {
        gfx.SetBlendMode(blendMode); //changes blending function
        var allTextures = allBlendModes[blendMode];
        foreach(Texture texture in allTextures.Keys)
        {
           gfx.SetTexture(texture); //changes texture
           foreach(List<RenderItem> itemBatch in allTextures[texture])
           {
             //Actually sent the vertices and draw triangles
             gfx.RenderBatch(itemBatch);
           }
        }
      }
   }
}
I left out the matrix one as I was writing it and don't feel like fixing it because I think you get the idea. I'm willing to bet this is an extremely common scenario in 2D rendering engines. How did you solve the same problem?

Orzo fucked around with this message at 19:39 on May 29, 2013

seiken
Feb 7, 2005

hah ha ha
Essentially this:

C++ code:
struct batched_texture {
  GlTexture sprite;
  ivec2 frame_size;
};

struct batched_sprite {
  fvec2 origin;
  fvec2 frame;
  float depth;
  float rotation;
  fvec4 colour;
};

typedef std::vector<batched_sprite> batched_sprite_list;
typedef std::map<batched_texture, batched_sprite_list,
                 batched_texture_order> batched_texture_map;

batched_texture_map _map;
So yeah, I guess I do something similar. Just the layered dictionaries are odd to me, can't you key a dictionary by a value-type struct in C#?

The thing is the only thing I batch by is the texture (and the frame size, but in practice that's constant per texture). Each quad of vertices are passed positions which are the corners of the rectangle defined by origin and frame_size; all the rest of the information in the batched_sprite structure is duplicated and passed to all four vertices as extra vertex attributes (so the interpolation is constant and I have access to these in the fragment shader). The camera position is a uniform variable. So I don't need to batch by any matrix stuff at all.

(You know you can pass a 4x4 matrix as four vec4 vertex attributes? You end up copying the matrix for every vertex, or every four vertices if you're on a recent enough GL that you can use vertex attribute divisor buffers, but this may well be faster than state changing for every matrix - I don't know how many different matrices you typically have per frame. If it's different for every sprite you draw then you're batching isn't accomplishing much. Edit: oh, it's just the view transformation? Cool then, but do you ever even use more than one in a frame?)

I don't know why you need to batch by layer rather than using a depth buffer, unless I'm misunderstanding what a layer is, and if I needed different blending modes I'd just use attributes again.

seiken fucked around with this message at 20:06 on May 29, 2013

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!

seiken posted:

So yeah, I guess I do something similar. Just the layered dictionaries are odd to me, can't you key a dictionary by a value-type struct in C#?
Yes, you can key with anything (and implement a custom GetHashCode() method for every object), but how would that help me?

Boil the problem down to its essence: you have an object with 3 properties and data: PropA, PropB, PropC, and Data. Your job is to send batches of items (data) to a renderer, but the rule is that any batch cannot have any mixed properties. Let's say I calculate a key with this formula: key = PropA + 1000 * PropB + 1000000 * PropC. So now what? I don't see how that helps me. A key may help me sort things in order, but they don't necessarily show me where the exact divisions between batches are. I guess you could use a formula to figure that out in the renderer, but now it's even more complex than the dictionary!

quote:

The thing is the only thing I batch by is the texture (and the frame size, but in practice that's constant per texture). Each quad of vertices are passed positions which are the corners of the rectangle defined by origin and frame_size; all the rest of the information in the batched_sprite structure is duplicated and passed to all four vertices as extra vertex attributes (so the interpolation is constant and I have access to these in the fragment shader). The camera position is a uniform variable. So I don't need to batch by any matrix stuff at all.
Fair enough, but what are you going to do when you implement a new blending mode? For example, regular alpha blending (transparancy) vs additive blending? You'll need to batch on another dimension.

Oh, and the reason I have batching by view is because I render multiple views at once. When my level scrolls from one screen to another, it's just rendering two separate levels. Also, my HUD is a totally different scene with its own camera.

quote:

(You know you can pass a 4x4 matrix as four vec4 vertex attributes? You end up copying the matrix for every vertex, or every four vertices if you're on a recent enough GL that you can use vertex attribute divisor buffers, but this may well be faster than state changing for every matrix - I don't know how many different matrices you typically have per frame. If it's different for every sprite you draw then you're batching isn't accomplishing much. Edit: oh, it's just the view transformation? Cool then, but do you ever even use more than one in a frame?)
Actually I didn't keep the Matrix4 key for that reason, because it's passed by-value and would copy all over the place--I opted to use an integer instead which represents an index into an array of Matrix4s.

quote:

I don't know why you need to batch by layer rather than using a depth buffer, unless I'm misunderstanding what a layer is, and if I needed different blending modes I'd just use attributes again.
Depth buffers don't play nice with blending, which is why 2D games typically render with a painter's algorithm instead of using the depth buffer.

Baldbeard
Mar 26, 2011


Thanks very much for this. Now I understand. I will try to implement this with my next -anything- that needs a camera.

SupSuper
Apr 8, 2009

At the Heart of the city is an Alien horror, so vile and so powerful that not even death can claim it.

RichardA posted:

In C++11 it works just fine with the >>'s. :colbert:
If only MSVC had full C++11 support. :negative:

seiken
Feb 7, 2005

hah ha ha

Orzo posted:

Yes, you can key with anything (and implement a custom GetHashCode() method for every object), but how would that help me?

Boil the problem down to its essence: you have an object with 3 properties and data: PropA, PropB, PropC, and Data. Your job is to send batches of items (data) to a renderer, but the rule is that any batch cannot have any mixed properties. Let's say I calculate a key with this formula: key = PropA + 1000 * PropB + 1000000 * PropC. So now what? I don't see how that helps me. A key may help me sort things in order, but they don't necessarily show me where the exact divisions between batches are. I guess you could use a formula to figure that out in the renderer, but now it's even more complex than the dictionary!
Oh, this wasn't about the batching or anything, I just thought it'd be less nasty syntax than a bunch of dicts :)

quote:

Fair enough, but what are you going to do when you implement a new blending mode? For example, regular alpha blending (transparancy) vs additive blending? You'll need to batch on another dimension.

Oh, and the reason I have batching by view is because I render multiple views at once. When my level scrolls from one screen to another, it's just rendering two separate levels. Also, my HUD is a totally different scene with its own camera.

Fair enough, I forgot about blending, sorry, it's because I doubt I'm actually going to use any blending on regular sprites. I have some fancy graphics effects planned, but they're going to be completely different things that need totally different kinds of multi-pass rendering algorithms anyway. My gut instinct would also be that I'd know exactly how many different kinds of blending passes I'd need, so there'd be no need to algorithmically batch them, not that doing so is a bad thing (though it does make the order less clear if they're order-dependent)

When you say you just keep an integer index into an array of matrices, you mean the array is in the shader so you don't have to switch state, right? I'm still pretty sure you shouldn't need to batch by view transformation.

seiken fucked around with this message at 21:21 on May 29, 2013

Polio Vax Scene
Apr 5, 2009



Is there a reason you can't use a ref Matrix4?

Adbot
ADBOT LOVES YOU

Schmerm
Sep 1, 2000
College Slice

SupSuper posted:

If only MSVC had full C++11 support. :negative:

It has enough to support >> 's and lots of useful things too (lambdas, unordered_maps). Initializer lists would be great, as would delegating/inheriting constructors.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply