Browse Source

Added support for specifying front facing polygon mode (CW or CCW) in RenderState.

Steve Grenier 12 năm trước cách đây
mục cha
commit
3611f7aa80
2 tập tin đã thay đổi với 73 bổ sung2 xóa
  1. 51 2
      gameplay/src/RenderState.cpp
  2. 22 0
      gameplay/src/RenderState.h

+ 51 - 2
gameplay/src/RenderState.cpp

@@ -18,6 +18,7 @@
 #define RS_STENCIL_WRITE 256
 #define RS_STENCIL_FUNC 512
 #define RS_STENCIL_OP 1024
+#define RS_FRONT_FACE 2048
 
 #define RS_ALL_ONES 0xFFFFFFFF
 
@@ -513,7 +514,7 @@ void RenderState::cloneInto(RenderState* renderState, NodeCloneContext& context)
 RenderState::StateBlock::StateBlock()
     : _cullFaceEnabled(false), _depthTestEnabled(false), _depthWriteEnabled(true), _depthFunction(RenderState::DEPTH_LESS),
       _blendEnabled(false), _blendSrc(RenderState::BLEND_ONE), _blendDst(RenderState::BLEND_ZERO),
-	  _stencilTestEnabled(false), _stencilWrite(RS_ALL_ONES), 
+      _cullFaceSide(CULL_FACE_SIDE_BACK), _frontFace(FRONT_FACE_CCW), _stencilTestEnabled(false), _stencilWrite(RS_ALL_ONES), 
 	  _stencilFunction(RenderState::STENCIL_ALWAYS), _stencilFunctionRef(0), _stencilFunctionMask(RS_ALL_ONES), 
 	  _stencilOpSfail(RenderState::STENCIL_OP_KEEP), _stencilOpDpfail(RenderState::STENCIL_OP_KEEP), _stencilOpDppass(RenderState::STENCIL_OP_KEEP),
       _bits(0L)
@@ -578,6 +579,11 @@ void RenderState::StateBlock::bindNoRestore()
         GL_ASSERT( glCullFace((GLenum)_cullFaceSide) );
         _defaultState->_cullFaceSide = _cullFaceSide;
     }
+    if ((_bits & RS_FRONT_FACE) && (_frontFace != _defaultState->_frontFace))
+    {
+        GL_ASSERT( glFrontFace((GLenum)_frontFace) );
+        _defaultState->_frontFace = _frontFace;
+    }
     if ((_bits & RS_DEPTH_TEST) && (_depthTestEnabled != _defaultState->_depthTestEnabled))
     {
         if (_depthTestEnabled) 
@@ -667,6 +673,12 @@ void RenderState::StateBlock::restore(long stateOverrideBits)
         _defaultState->_bits &= ~RS_CULL_FACE_SIDE;
         _defaultState->_cullFaceSide = RenderState::CULL_FACE_SIDE_BACK;
     }
+    if (!(stateOverrideBits & RS_FRONT_FACE) && (_defaultState->_bits & RS_FRONT_FACE))
+    {
+        GL_ASSERT( glFrontFace((GLenum)GL_CCW) );
+        _defaultState->_bits &= ~RS_FRONT_FACE;
+        _defaultState->_frontFace = RenderState::FRONT_FACE_CCW;
+    }
     if (!(stateOverrideBits & RS_DEPTH_TEST) && (_defaultState->_bits & RS_DEPTH_TEST))
     {
         GL_ASSERT( glDisable(GL_DEPTH_TEST) );
@@ -742,6 +754,7 @@ void RenderState::StateBlock::cloneInto(StateBlock* state)
     state->_blendSrc = _blendSrc;
     state->_blendDst = _blendDst;
     state->_cullFaceSide = _cullFaceSide;
+    state->_frontFace = _frontFace;
 	state->_stencilTestEnabled = _stencilTestEnabled;
 	state->_stencilWrite = _stencilWrite;
 	state->_stencilFunction = _stencilFunction;
@@ -882,11 +895,29 @@ static RenderState::CullFaceSide parseCullFaceSide(const char* value)
         return RenderState::CULL_FACE_SIDE_FRONT_AND_BACK;
     else
     {
-        GP_ERROR("Unsupported cull face side value (%s). Will default to BACK if errors are treated as warnings)", value);
+        GP_ERROR("Unsupported cull face side value (%s). Will default to BACK if errors are treated as warnings.", value);
         return RenderState::CULL_FACE_SIDE_BACK;
     }
 }
 
+static RenderState::FrontFace parseFrontFace(const char* value)
+{
+    GP_ASSERT(value);
+
+    // Convert string to uppercase for comparison
+    std::string upper(value);
+    std::transform(upper.begin(), upper.end(), upper.begin(), (int(*)(int))toupper);
+    if (upper == "CCW")
+        return RenderState::FRONT_FACE_CCW;
+    else if (upper == "CW")
+        return RenderState::FRONT_FACE_CW;
+    else
+    {
+        GP_ERROR("Unsupported front face side value (%s). Will default to CCW if errors are treated as warnings.", value);
+        return RenderState::FRONT_FACE_CCW;
+    }
+}
+
 static RenderState::StencilFunction parseStencilFunc(const char* value)
 {
     GP_ASSERT(value);
@@ -971,6 +1002,10 @@ void RenderState::StateBlock::setState(const char* name, const char* value)
     {
         setCullFaceSide(parseCullFaceSide(value));
     }
+    else if (strcmp(name, "frontFace") == 0)
+    {
+        setFrontFace(parseFrontFace(value));
+    }
     else if (strcmp(name, "depthTest") == 0)
     {
         setDepthTest(parseBoolean(value));
@@ -1089,6 +1124,20 @@ void RenderState::StateBlock::setCullFaceSide(CullFaceSide side)
     }
 }
 
+void RenderState::StateBlock::setFrontFace(FrontFace winding)
+{
+    _frontFace = winding;
+    if (_frontFace == FRONT_FACE_CCW)
+    {
+        // Default front face
+        _bits &= ~RS_FRONT_FACE;
+    }
+    else
+    {
+        _bits |= RS_FRONT_FACE;
+    }
+}
+
 void RenderState::StateBlock::setDepthTest(bool enabled)
 {
     _depthTestEnabled = enabled;

+ 22 - 0
gameplay/src/RenderState.h

@@ -180,6 +180,17 @@ public:
         CULL_FACE_SIDE_FRONT_AND_BACK = GL_FRONT_AND_BACK
     };
 
+    /**
+     * Defines the winding of vertices in faces that are considered front facing.
+     *
+     * The initial front face mode is set to FRONT_FACE_CCW.
+     */
+    enum FrontFace
+    {
+        FRONT_FACE_CW,
+        FRONT_FACE_CCW
+    };
+
 	/**
      * Defines the supported stencil compare functions.
 	 * 
@@ -280,10 +291,20 @@ public:
          * Sets the side of the facets to cull.
          *
          * When not explicitly set, the default is to cull back-facing facets.
+         *
          * @param side The side to cull.
          */
         void setCullFaceSide(CullFaceSide side);
 
+        /**
+         * Sets the winding for front facing polygons.
+         *
+         * By default, counter-clockwise wound polygons are considered front facing.
+         *
+         * @param winding The winding for front facing polygons.
+         */
+        void setFrontFace(FrontFace winding);
+
         /**
          * Toggles depth testing.
          *
@@ -396,6 +417,7 @@ public:
         Blend _blendSrc;
         Blend _blendDst;
         CullFaceSide _cullFaceSide;
+        FrontFace _frontFace;
 		bool _stencilTestEnabled;
 		unsigned int _stencilWrite;
 		StencilFunction _stencilFunction;