Page 1 of 1

Render state cleanup

Posted: Sat Jan 25, 2014 11:15 pm
by Luomu
I'd like to remove these individual state change functions in Renderer:

Code: Select all

virtual bool SetBlendMode(BlendMode type)
virtual bool SetDepthTest(bool enabled)
virtual bool SetDepthWrite(bool enabled)
virtual bool SetWireFrameMode(bool enabled)
//twoSided property in MaterialDesc
//may be others scattered around
And combine them in what is usually called render state blocks/statesets/etc. So, instead of changing an individual state you create a render state set based on a description and then just apply it before drawing. Like this:

Code: Select all

//at init time
RenderStateDesc desc;
desc.depthTest = false;
desc.blendMode = BLEND_SOLID;
RenderState* state = renderer->CreateRenderState(desc);

//at each render call
renderer->SetRenderState(state);
renderer->DrawStuff(...)
What's good about it:
- there are no leaks as everyone is expected to set the correct state before drawing
- redundant changes can be avoided by just comparing pointers. State sets are shared, and
cached by renderer.

Implementing this is simple but I'm asking first because I would update all the current use cases at the same time and that's some amount of work.

Re: Render state cleanup

Posted: Sun Jan 26, 2014 6:31 am
by robn
Yes yes yes. I attempted this over a year ago but there was too much raw GL use in the core to make it work well.

Code: Select all

//at each render call
renderer->SetRenderState(state);
renderer->DrawStuff(...)
I had sort of thought that this would be more like:

Code: Select all

renderer->DrawStuff(state, ...)
Just because then there's no way to ever have state leak. If your stuff looks wrong its because you screwed the state up. I guess the difference is largely academic though.

Would you do batching and state sorting as well? I suppose that's an implementation detail to an extent, and can be done later.

Re: Render state cleanup

Posted: Sun Jan 26, 2014 1:16 pm
by FluffyFreak
Yes this sounds good to me, a better interface and separates us from the implementation a bit better.

Re: Render state cleanup

Posted: Mon Jan 27, 2014 11:14 pm
by Luomu
Started yesterday in https://github.com/Luomu/pioneer/tree/statesets
robn wrote: I had sort of thought that this would be more like:

Code: Select all

renderer->DrawStuff(state, ...)
Yeah, that's a good idea actually. Too bad we have eight different DrawStuff functions. I'll do it for DrawTriangles at least. Here we see again how days of coding can save you hours of planning...
Would you do batching and state sorting as well?
This is only going to replace the aforementioned state change functions. Larger refactoring of object drawing has been started at least three times but it's... tricky. So maybe the immediate "draw stuff now" style suits Pioneer better. Planets mix opaque and transparent drawing, and then they sometimes clear depth buffer when they are far away - that's pretty specific. We could try adding different render passes (distant objects, opaque, transparent) and then some helper for geometry batching (merge simple geometry each frame to reduce draw calls).

I don't actually want to keep tweaking the rendering forever, but I'd like to fix these two issues:
1) Better sorting
2) Replace the gross StaticMesh with some simpler vertex buffer, use it more widely (planets)

Re: Render state cleanup

Posted: Tue Jan 28, 2014 8:39 am
by FluffyFreak
I think we need to do some kind of [distant objects, opaque, transparent] style batching and sorting where relevent.

I'd like to add clouds, trees, grass, imposters and other bits and bobs that would need depth sorting for alpha - be happy to help out with doing it otherwise I'll just have to do myself later on :D

Re: Render state cleanup

Posted: Tue Jan 28, 2014 9:03 am
by robn
Luomu wrote:This is only going to replace the aforementioned state change functions. Larger refactoring of object drawing has been started at least three times but it's... tricky.
Yeah, I think I tried one too. I was always under the impression that if we could properly encapsulate the state, including stuff like "clear depth buffer", then we could cause DrawStuff(state, ...) to simply add to a queue instead of draw immediately. Then if the sort comparator includes knowledge of "distant object", "opaque", "transparent" etc it should all go nicely, right?

But we really don't have to even think about it now. The API itself wouldn't change, or only minimally. So yeah, just leave it.