Skip to main content

News

Topic: TurboSphere (Read 193958 times) previous topic - next topic

0 Members and 10 Guests are viewing this topic.
Re: TurboSphere
Reply #300
I've put up a draft of what the SpriteBatch API will look like. I'd appreciate any feedback on it. I've never defined an out-facing API like this before.

What do you guys think? Is the fewer-functions-with-more-options approach better or worse than the old Sphere approach? Should I make it more like the old Sphere API, or is this a better idea?

Anyway, screeny time again!
Texture sorting/fitting and loading spritebatch textures from both surfaces (the red X) and images (the Sphere logo). Loading textures from objects has almost identical overhead to blitting the object.
  • Last Edit: November 24, 2013, 11:06:30 pm by Flying Jester

  • N E O
  • [*][*][*][*][*]
  • Administrator
  • Senior Administrator
Re: TurboSphere
Reply #301
I'm a little foggy on it; can you explain what SpriteBatch is and what it would be used for?

Re: TurboSphere
Reply #302
The sprite batcher is a way to specify a list of graphics operations (image blits and primitives). You then just call its draw operation, and all the operations in its list are done. Blitting images and drawing primitives this way is faster (by a significant amount).

It removes the function call overhead, makes texture atlases, lowers the number of GL state changes (by a lot) because the GL state is known for all the operations in the list and what order they will occur in, and uploads most of the information to the GPU only once.

You could use it for HUDs, menus, even possibly special effects. It is, however, best suited for map and tiling engines, and it will be the graphical backend for the TurboSphere map engine.

On a side note: TurboSphere now has hardware occlusion support. Occluded drawing (things that will be overlapped by something else before FlipScreen is called) is skipped when the hardware supports this. You could see up to a 10% performance improvement in certain cases. Such as that last screenshot I posted. And it's not just limited to images with uninterrupted, total opaqueness--notice the less-than full alpha in the red surfaces.
  • Last Edit: November 25, 2013, 05:48:01 pm by Flying Jester

  • DaVince
  • [*][*][*][*][*]
  • Administrator
  • Used Sphere for, like, half my life
Re: TurboSphere
Reply #303
Sprite batching looks like a clever technique. The API looks a little bit confusing at first, though.

You say "'tex' is the index of the texture to draw", but how do we know this index? Does spritebatch.addTexture() return this index to you? Do we have any better ways to find it, like passing the actual texture file as an argument so it can find (or otherwise add) this image in the array?

Why do addTexture and pushTexture look so different? They seem to do very different things, but their naming is very close to each other, which will only cause confusion. One adds a texture into the buffer, and one adds a drawing operation to the queue, right?

Also, is there any reason you're not overloading anything? You could easily just have an add() function that accepts Image, Surface, TextureOperation or PrimitiveOperation object. Or is this a big no-no to do?

Re: TurboSphere
Reply #304

Sprite batching looks like a clever technique. The API looks a little bit confusing at first, though.

You say "'tex' is the index of the texture to draw", but how do we know this index? Does spritebatch.addTexture() return this index to you? Do we have any better ways to find it, like passing the actual texture file as an argument so it can find (or otherwise add) this image in the array?

Why do addTexture and pushTexture look so different? They seem to do very different things, but their naming is very close to each other, which will only cause confusion. One adds a texture into the buffer, and one adds a drawing operation to the queue, right?


Yes, addTexture adds a new texture to the atlas, pushTexture adds a new operation to the spritebatch. I could certainly make it so that addTexture returns an index. The trouble with passing an image into pushTexture is that, while it is quite possible to do when dealing with textures already added to the spritebatch, it could get messy if you pass in any arbitrary image.


Also, is there any reason you're not overloading anything? You could easily just have an add() function that accepts Image, Surface, TextureOperation or PrimitiveOperation object. Or is this a big no-no to do?


I certainly could overload it, no reason not to. As in, have objects for each kind of operation. That's actually a better idea.

On a side note, over the weekend I fixed bugs in AreKeysPressed and GetKey. It was reporting 'phantom' key presses, and GetKey always missed the first key press when the engine started. It's fixed in the Git repo now.
  • Last Edit: December 01, 2013, 09:53:11 pm by Flying Jester

Re: TurboSphere
Reply #305
I've added a much better guide to compiling TurboSphere to the Read me on GitHub.

I've been playing around with more advanced OpenGL in TurboSphere. I've almost got it working with OpenGL 3.2 (which is only eight years old...new OpenGL like 3.3, 4.x expects a lot more from the programmer), and have most of the pointer-based drawing code--which only slightly better than raw immediate mode--removed. This change will probably be merged and released for Windows early in the new year.

I've also confirmed the latest release to work with Mesa 3D on Windows. This is excellent if you have an Intel integrated GPU, which have spotty native OpenGL support.

That will also mark the addition of script-exposed Shaders. I'm not entirely sure if I want to make the default shaders baked-in to the executable or not...but I probably won't, since it will save a lot of time debugging if I don't have to recompile the whole graphics plugin to test changes to shaders.

So, since we've discussed shaders in Sphere engines before, here's a question for anyone.

What would you like the exposed shader API to look like?
  • Last Edit: December 05, 2013, 08:08:02 pm by Flying Jester

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: TurboSphere
Reply #306
The shader API is a hard one to implement and actually stems from your blitting model (API). In traditional Sphere blitting you would do this:
Code: [Select]

Image.blit(x, y[, shader]);
Image.zoomBlit(x, y, z, [, shader]);


But if you do blits differently:
Code: [Select]

Image.shader = shader;
Image.blit(x, y);


Then it get's easier.

Furthermore, as for the shader itself, we have to set and get properties from it, create new instances of it, etc. So by the way you are doing things it would look like:
Code: [Select]

var shader = new Shader('path_to_shader.glsl');
shader.setProperty(0, Image.texture);
shader.setProperty(1, 5.0);
//...


Then you can have a new /shaders/ folder as one of the many standard folders used by Sphere games.
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

Re: TurboSphere
Reply #307
I definitely wouldn't want it to be a parameter for drawing operations. It should be, in some way, a part of a per-object and/or global (default) state.

Hmm...as far as per-image shaders, it would also be good to be able to set the current shader for all drawing. Perhaps as well to specify different default shaders for textured and un-textured drawing?

For how a shader would look out of script proper, I've been looking at Byuu's Quark for instpiration and guidance. I like the idea of a simple manifest file that specifies shader files that compose the shader program. It could also be used to specify certain whether or not to supply certain uniforms to the shader.

What about on the GLSL side? Again, I've been looking at Quark, but I'm not sure about having variable output size. I would like having most of the uniforms that are exposedm, though.

EDIT:
I have to add, this recent bit about of first working on the MapEngine, then the SpriteBatch, and now upgrading the OpenGL version and adding shaders isn't just some bout of lack of concentration or me having a very short attention span.
These are all related issues and concepts. The SpriteBatch is a backend for the MapEngine, which will automate a lot of graphical portions (and several optimizations) for the MapEngine, as well as provide this feature to script. But it works like modern OpenGL does--more like the map engine, less like the normal drawing API of Sphere. And when I switched to OpenGL, I made certain assumptions and decisions of how to do it that really only facilatated the drawing API, which works a lot like OpenGL immediate mode. Which was deprecated in OpenGL eight years ago.

It will probably be best to just get this all done in one clean pass. Remove the deprecated immediate-mode code by switching to OpenGL buffers and arrays, add shaders, and implement a generic texture atlasing and OpenGL array generator. This will make the SpriteBatcher much more efficient, give TurboSphere a much more modern OpenGL implementation, which will also be better suited to the SpriteBatcher, which will make the map engine easier to implement. It's just layers of me discovering what should be done before I work on what I originally planned on doing.

I'm trying to fix fundamental shortcomings and limitations of the current implementation of TurboSphere.
  • Last Edit: December 06, 2013, 12:29:44 am by Flying Jester

  • N E O
  • [*][*][*][*][*]
  • Administrator
  • Senior Administrator
Re: TurboSphere
Reply #308
I recommend shaders be global instead of per-object. Imagine the performance hit of even 20 spritesets onscreen with 20 different shaders applied!

A shader could be applied to MapEngine to globally affect all maps within that running map engine, with a ChangeMapShader (or similarly named) function added to change the map engine's shader on the fly. It would take care of most of the use cases for the ColorMatrix object (ie, applying environmental visual transformation effects like fog or dawn/dusk, etc).

A shader could be applied to global spriteset rendering, say to desaturate all the sprites on the screen but not the map during a Shakespeare-like aside or soliloquy or narration and then resaturate them afterward; for doing it per sprite you might as well transform a person's spriteset like before to prevent the hit on performance.

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: TurboSphere
Reply #309
Yeah, the spriteset level would be best. I wanted per image as because I was thinking of effects like invisibility, and various other powerups get unique shaders for only specific sprites on a map. I also de see the use for global shaders like bloom, color, or fog shaders. I also see shaders for lamplight and other 2d type light sources as well. So a good shader API has to affect all layers of shader use.
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

Re: TurboSphere
Reply #310
And whole-scene effects like fish-eye, stereograph 3D, and--most exciting to me--simple lighting effects.

Switching shaders doesn't have too huge a performance penalty from what I've seen, although it's not exactly cheap either. I probably wouldn't want to have them be different for every image, but per-SpriteBatch might be good. That would be comparable to per-spriteset or per-map shaders. And it would be just that on the backend.

Re: TurboSphere
Reply #311
Behold, TurboSphere rendered using OpenGL Shading Language 1.5. The images and surfaces use buffers instead of pure pointers. Still not full vertex arrays (what I am working towards), though. I needed shading working first.

I'll need to redo all the drawing code. Fortunately, most plugins don't do a lot of it except the SDL_GL plugin. And that one uses the TS_Image object pretty exclusively for textures, so it's quick to modify.
And besides, I want to reduce the redundant primitive functions in SDL_GL anyway.

I've been thinking, and...
It would be trivial to add basic compositing. As in, whole-scene shading that takes the output at the end of a FlipScreen, and applies a shader to it, then draws it to the screen proper. That would possibly be the best way to implement filters and bloom or HDR-like effects. Plus, it would make grabbing the screen and saving screenshots a lot more efficient, although at a slight hit to performance (about one ms per frame, plus time to run a scene shader). I could very easily make it toggle-able at runtime, and disable it when no whole-scene shaders are in use, or even enable it for a single frame to grab a screenshot, and then turn it off again.

That would also make it simple to redirect the video output of TurboSphere to another window or output. I have no idea the use of that, but it would be...something. It would NOT be the best solution for recording, but it would still be more efficient for it than the way things are now.
  • Last Edit: December 10, 2013, 05:41:57 am by Flying Jester

  • DaVince
  • [*][*][*][*][*]
  • Administrator
  • Used Sphere for, like, half my life
Re: TurboSphere
Reply #312
Woo, good work. :)


That would also make it simple to redirect the video output of TurboSphere to another window or output. I have no idea the use of that, but it would be...something. It would NOT be the best solution for recording, but it would still be more efficient for it than the way things are now.

I like this idea. Just imagining running games from a launcher, and they're displayed in the launcher window...

Re: TurboSphere
Reply #313
Compositing is working now. Thing is, I know that you can pass handles to GL contexts around...I just have no idea how it is done.

Fun fact: GL framebuffers don't use the global ortho and projection settings. The colour echoing was unrelated.

Pic just for fun, it's fixed now.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: TurboSphere
Reply #314
So all this talk about shaders has me curious. I know shaders are used in 3D games for special effects, but what would be some applications of shaders in a 2D game? I'm straining, but for the life of me I can't imagine any (non-gimmicky) use cases for them.
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub