Refactoring of RenderState

I am starting the initial proposal here since the discussion page on github seem not to be use.

With the addition of more opengl features, in this case the

  • glBlendXXXXSeparate
  • glStencilXXXXSeparate

the RenderState class gets messier. I am proposing a refactoring to something like in the case of the StencilTest

public class RenderState {
    @Setter
    @Getter
    StencilTest stencilTest;

    public interface StencilTest {

    }

    public enum StencilOperation {
        Keep,
        Zero,
        Replace,
        Increment,
        IncrementWrap,
        Decrement,
        DecrementWrap,
        Invert
    }

    public enum StencilFunction {
        Never,
        Equal,
        Less,
        LessOrEqual,
        Greater,
        GreaterOrEqual,
        NotEqual,
        Always
    }

    @AllArgsConstructor
    public static class StencilTestFunction implements StencilTest {
        StencilOperation stencilFailOperation;
        StencilOperation depthFailOperation;
        StencilOperation depthPassOperation;
        StencilFunction function;
        int reference;
        int mask;
    }

    @AllArgsConstructor
    public static class StencilTestFunctionSeparate implements StencilTest {
        StencilTestFunction frontFunction;
        StencilTestFunction backFunction;
    }
}

Instead of currently only supporting the separate version of the stencil test this would add the feature of the regular one while simplifying the usage from:

RenderState additionalRenderState = outlineMaterial.getAdditionalRenderState();
additionalRenderState.setStencil(true,
                    RenderState.StencilOperation.Keep, //front triangle fails stencil test
                    RenderState.StencilOperation.Keep, //front triangle fails depth test
                    RenderState.StencilOperation.Keep, //front triangle passes depth test
                    RenderState.StencilOperation.Keep, //back triangle fails stencil test
                    RenderState.StencilOperation.Keep, //back triangle fails depth test
                    RenderState.StencilOperation.Keep, //back triangle passes depth test
                    RenderState.TestFunction.Equal, //front triangle stencil test function
                    RenderState.TestFunction.Equal);    //back triangle stencil test function
additionalRenderState.setFrontStencilReference(1);
additionalRenderState.setBackStencilReference(1);
additionalRenderState.setFrontStencilMask(0xFF);
additionalRenderState.setBackStencilMask(0xFF);

to:

    private static StencilTestFunction OUTLINE_STENCIL_TEST = new StencilTestFunction(
            StencilOperation.Keep,
            StencilOperation.Keep,
            StencilOperation.Keep,
            StencilFunction.Equal,
            1,0xff);

    private static StencilTest OUTLINE_STENCIL_TEST_SEPARATE = new StencilTestFunctionSeparate(
            OUTLINE_STENCIL_TEST, OUTLINE_STENCIL_TEST
    );

RenderState additionalRenderState = outlineMaterial.getAdditionalRenderState();
additionalRenderState.setStencilTest(OUTLINE_STENCIL_TEST) // basic stencil test
additionalRenderState.setStencilTest(OUTLINE_STENCIL_TEST_SEPARATE ) //separate stencil test

A very similar refactoring would be needed for blend modes, with the possible exception that the blend mode change might be possible in a backwards compatible way. The stencil test would cause a compile breaking change, with the option to retain backwards compability if we keep the current setters. (and hack around)

2 Likes

It seems like a good idea to me. I agree wholeheartedly that RenderState is a mess. It has already caused several different issues to crop up because it’s so confusing to work with.