Przeglądaj źródła

Add a RenderState member for cull face side.

Add a new RenderState variable named 'cullFaceSide' for changing between
FRONT, BACK and FRONT_AND_BACK values.

This is useful in same materials, such as when implementing cel shading.
Üstün Ergenoğlu 12 lat temu
rodzic
commit
d047de4351

+ 1 - 0
gameplay/CMakeLists.txt

@@ -492,6 +492,7 @@ set(GAMEPLAY_LUA
     src/lua/lua_RenderStateAutoBinding.h
     src/lua/lua_RenderStateBlend.cpp
     src/lua/lua_RenderStateBlend.h
+    src/lua/lua_RenderStateCullFaceSide.cpp
     src/lua/lua_RenderStateDepthFunction.cpp
     src/lua/lua_RenderStateDepthFunction.h
     src/lua/lua_RenderStateStateBlock.cpp

+ 1 - 0
gameplay/android/jni/Android.mk

@@ -237,6 +237,7 @@ LOCAL_SRC_FILES := \
     lua/lua_RenderState.cpp \
     lua/lua_RenderStateAutoBinding.cpp \
     lua/lua_RenderStateBlend.cpp \
+    lua/lua_RenderStateCullFaceSide.cpp \
     lua/lua_RenderStateDepthFunction.cpp \
     lua/lua_RenderStateStateBlock.cpp \
     lua/lua_RenderTarget.cpp \

+ 3 - 1
gameplay/gameplay.vcxproj

@@ -229,6 +229,7 @@
     <ClCompile Include="src\lua\lua_RenderState.cpp" />
     <ClCompile Include="src\lua\lua_RenderStateAutoBinding.cpp" />
     <ClCompile Include="src\lua\lua_RenderStateBlend.cpp" />
+    <ClCompile Include="src\lua\lua_RenderStateCullFaceSide.cpp" />
     <ClCompile Include="src\lua\lua_RenderStateDepthFunction.cpp" />
     <ClCompile Include="src\lua\lua_RenderStateStateBlock.cpp" />
     <ClCompile Include="src\lua\lua_RenderTarget.cpp" />
@@ -509,6 +510,7 @@
     <ClInclude Include="src\lua\lua_RenderState.h" />
     <ClInclude Include="src\lua\lua_RenderStateAutoBinding.h" />
     <ClInclude Include="src\lua\lua_RenderStateBlend.h" />
+    <ClInclude Include="stc\lua\lua_RenderStateCullFaceSide.h" />
     <ClInclude Include="src\lua\lua_RenderStateDepthFunction.h" />
     <ClInclude Include="src\lua\lua_RenderStateStateBlock.h" />
     <ClInclude Include="src\lua\lua_RenderTarget.h" />
@@ -1094,4 +1096,4 @@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
+</Project>

+ 12 - 0
gameplay/gameplay.xcodeproj/project.pbxproj

@@ -1155,6 +1155,10 @@
 		BD26373616CF865B00CFE15F /* Vector2.inl in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E39147D8FF50000361E /* Vector2.inl */; settings = {ATTRIBUTES = (Public, ); }; };
 		BD26373716CF865B00CFE15F /* Vector3.inl in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E3C147D8FF50000361E /* Vector3.inl */; settings = {ATTRIBUTES = (Public, ); }; };
 		BD26373816CF865B00CFE15F /* Vector4.inl in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E3F147D8FF50000361E /* Vector4.inl */; settings = {ATTRIBUTES = (Public, ); }; };
+		C054CBE5172EF541000B7DC3 /* lua_RenderStateCullFaceSide.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C054CBE3172EF541000B7DC3 /* lua_RenderStateCullFaceSide.cpp */; };
+		C054CBE6172EF541000B7DC3 /* lua_RenderStateCullFaceSide.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C054CBE3172EF541000B7DC3 /* lua_RenderStateCullFaceSide.cpp */; };
+		C054CBE7172EF541000B7DC3 /* lua_RenderStateCullFaceSide.h in Headers */ = {isa = PBXBuildFile; fileRef = C054CBE4172EF541000B7DC3 /* lua_RenderStateCullFaceSide.h */; };
+		C054CBE8172EF541000B7DC3 /* lua_RenderStateCullFaceSide.h in Headers */ = {isa = PBXBuildFile; fileRef = C054CBE4172EF541000B7DC3 /* lua_RenderStateCullFaceSide.h */; };
 		DD1FF47216DBD8F9000B42EF /* Platform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD1FF47116DBD8F9000B42EF /* Platform.cpp */; };
 		DD1FF47316DBD8F9000B42EF /* Platform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD1FF47116DBD8F9000B42EF /* Platform.cpp */; };
 		F1616ABC1614E24B008DD8B7 /* MathUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F1616ABB1614E24B008DD8B7 /* MathUtil.cpp */; };
@@ -1766,6 +1770,8 @@
 		BD2636E216CF5B7400CFE15F /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk/System/Library/Frameworks/OpenGLES.framework; sourceTree = DEVELOPER_DIR; };
 		BD2636E316CF5B7400CFE15F /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
 		BD2636E416CF5B7400CFE15F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
+		C054CBE3172EF541000B7DC3 /* lua_RenderStateCullFaceSide.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lua_RenderStateCullFaceSide.cpp; sourceTree = "<group>"; };
+		C054CBE4172EF541000B7DC3 /* lua_RenderStateCullFaceSide.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lua_RenderStateCullFaceSide.h; sourceTree = "<group>"; };
 		DD1FF47116DBD8F9000B42EF /* Platform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Platform.cpp; path = src/Platform.cpp; sourceTree = SOURCE_ROOT; };
 		F1616ABB1614E24B008DD8B7 /* MathUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MathUtil.cpp; path = src/MathUtil.cpp; sourceTree = SOURCE_ROOT; };
 		F18024A31627000D001BFF87 /* gameplay-main-ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "gameplay-main-ios.mm"; path = "src/gameplay-main-ios.mm"; sourceTree = SOURCE_ROOT; };
@@ -2341,6 +2347,8 @@
 				42BCD41215EFD0F300C0E076 /* lua_RenderStateAutoBinding.h */,
 				42BCD41315EFD0F300C0E076 /* lua_RenderStateBlend.cpp */,
 				42BCD41415EFD0F300C0E076 /* lua_RenderStateBlend.h */,
+				C054CBE3172EF541000B7DC3 /* lua_RenderStateCullFaceSide.cpp */,
+				C054CBE4172EF541000B7DC3 /* lua_RenderStateCullFaceSide.h */,
 				B661732D16A61A4B0083A307 /* lua_RenderStateDepthFunction.cpp */,
 				B661732E16A61A4B0083A307 /* lua_RenderStateDepthFunction.h */,
 				42BCD41515EFD0F300C0E076 /* lua_RenderStateStateBlock.cpp */,
@@ -2792,6 +2800,7 @@
 				42A5031316E8F06500F0246C /* ImageControl.h in Headers */,
 				42A5031916E8F08900F0246C /* lua_ImageControl.h in Headers */,
 				42A5031F16E8F0B800F0246C /* lua_TerrainListener.h in Headers */,
+				C054CBE7172EF541000B7DC3 /* lua_RenderStateCullFaceSide.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -3098,6 +3107,7 @@
 				42A5031416E8F06500F0246C /* ImageControl.h in Headers */,
 				42A5031A16E8F08900F0246C /* lua_ImageControl.h in Headers */,
 				42A5032016E8F0B800F0246C /* lua_TerrainListener.h in Headers */,
+				C054CBE8172EF541000B7DC3 /* lua_RenderStateCullFaceSide.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -3473,6 +3483,7 @@
 				42A5031116E8F06500F0246C /* ImageControl.cpp in Sources */,
 				42A5031716E8F08900F0246C /* lua_ImageControl.cpp in Sources */,
 				42A5031D16E8F0B800F0246C /* lua_TerrainListener.cpp in Sources */,
+				C054CBE5172EF541000B7DC3 /* lua_RenderStateCullFaceSide.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -3753,6 +3764,7 @@
 				42A5031216E8F06500F0246C /* ImageControl.cpp in Sources */,
 				42A5031816E8F08900F0246C /* lua_ImageControl.cpp in Sources */,
 				42A5031E16E8F0B800F0246C /* lua_TerrainListener.cpp in Sources */,
+				C054CBE6172EF541000B7DC3 /* lua_RenderStateCullFaceSide.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 51 - 0
gameplay/src/RenderState.cpp

@@ -13,6 +13,7 @@
 #define RS_DEPTH_TEST 8
 #define RS_DEPTH_WRITE 16
 #define RS_DEPTH_FUNC 32
+#define RS_CULL_FACE_SIDE 64
 
 namespace gameplay
 {
@@ -557,6 +558,11 @@ void RenderState::StateBlock::bindNoRestore()
             GL_ASSERT( glDisable(GL_CULL_FACE) );
         _defaultState->_cullFaceEnabled = _cullFaceEnabled;
     }
+    if ((_bits & RS_CULL_FACE_SIDE) && (_cullFaceSide != _defaultState->_cullFaceSide))
+    {
+        GL_ASSERT( glCullFace((GLenum)_cullFaceSide) );
+        _defaultState->_cullFaceSide = _cullFaceSide;
+    }
     if ((_bits & RS_DEPTH_TEST) && (_depthTestEnabled != _defaultState->_depthTestEnabled))
     {
         if (_depthTestEnabled) 
@@ -609,6 +615,12 @@ void RenderState::StateBlock::restore(long stateOverrideBits)
         _defaultState->_bits &= ~RS_CULL_FACE;
         _defaultState->_cullFaceEnabled = false;
     }
+    if (!(stateOverrideBits & RS_CULL_FACE_SIDE) && (_defaultState->_bits & RS_CULL_FACE_SIDE))
+    {
+        GL_ASSERT( glCullFace((GLenum)GL_BACK) );
+        _defaultState->_bits &= ~RS_CULL_FACE_SIDE;
+        _defaultState->_cullFaceSide = RenderState::CULL_FACE_SIDE_BACK;
+    }
     if (!(stateOverrideBits & RS_DEPTH_TEST) && (_defaultState->_bits & RS_DEPTH_TEST))
     {
         GL_ASSERT( glDisable(GL_DEPTH_TEST) );
@@ -655,6 +667,7 @@ void RenderState::StateBlock::cloneInto(StateBlock* state)
     state->_blendEnabled = _blendEnabled;
     state->_blendSrc = _blendSrc;
     state->_blendDst = _blendDst;
+    state->_cullFaceSide = _cullFaceSide;
     state->_bits = _bits;
 }
 
@@ -744,6 +757,26 @@ static RenderState::DepthFunction parseDepthFunc(const char* value)
     }
 }
 
+static RenderState::CullFaceSide parseCullFaceSide(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 == "BACK")
+        return RenderState::CULL_FACE_SIDE_BACK;
+    else if (upper == "FRONT")
+        return RenderState::CULL_FACE_SIDE_FRONT;
+    else if (upper == "FRONT_AND_BACK")
+        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);
+        return RenderState::CULL_FACE_SIDE_BACK;
+    }
+}
+
 void RenderState::StateBlock::setState(const char* name, const char* value)
 {
     GP_ASSERT(name);
@@ -764,6 +797,10 @@ void RenderState::StateBlock::setState(const char* name, const char* value)
     {
         setCullFace(parseBoolean(value));
     }
+    else if (strcmp(name, "cullFaceSide") == 0)
+    {
+        setCullFaceSide(parseCullFaceSide(value));
+    }
     else if (strcmp(name, "depthTest") == 0)
     {
         setDepthTest(parseBoolean(value));
@@ -836,6 +873,20 @@ void RenderState::StateBlock::setCullFace(bool enabled)
     }
 }
 
+void RenderState::StateBlock::setCullFaceSide(CullFaceSide side)
+{
+    _cullFaceSide = side;
+    if (_cullFaceSide == CULL_FACE_SIDE_BACK)
+    {
+        // Default cull side
+        _bits &= ~RS_CULL_FACE_SIDE;
+    }
+    else
+    {
+        _bits |= RS_CULL_FACE_SIDE;
+    }
+}
+
 void RenderState::StateBlock::setDepthTest(bool enabled)
 {
     _depthTestEnabled = enabled;

+ 20 - 0
gameplay/src/RenderState.h

@@ -169,6 +169,17 @@ public:
         DEPTH_ALWAYS = GL_ALWAYS
     };
 
+    /**
+     * Defines culling criteria for front-facing, back-facing and both-side 
+     * facets.
+     */
+    enum CullFaceSide
+    {
+        CULL_FACE_SIDE_BACK = GL_BACK,
+        CULL_FACE_SIDE_FRONT = GL_FRONT,
+        CULL_FACE_SIDE_FRONT_AND_BACK = GL_FRONT_AND_BACK
+    };
+
     /**
      * Defines a block of fixed-function render states that can be applied to a
      * RenderState object.
@@ -226,6 +237,14 @@ public:
          */
         void setCullFace(bool enabled);
 
+        /**
+         * 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);
+
         /**
          * Toggles depth testing.
          *
@@ -297,6 +316,7 @@ public:
         bool _blendEnabled;
         Blend _blendSrc;
         Blend _blendDst;
+        CullFaceSide _cullFaceSide;
         long _bits;
 
         static StateBlock* _defaultState;

+ 1 - 0
gameplay/src/lua/lua_RenderState.cpp

@@ -12,6 +12,7 @@
 #include "lua_RenderStateAutoBinding.h"
 #include "lua_RenderStateBlend.h"
 #include "lua_RenderStateDepthFunction.h"
+#include "lua_RenderStateCullFaceSide.h"
 
 namespace gameplay
 {

+ 35 - 0
gameplay/src/lua/lua_RenderStateCullFaceSide.cpp

@@ -0,0 +1,35 @@
+#include "Base.h"
+#include "lua_RenderStateCullFaceSide.h"
+
+namespace gameplay
+{
+
+static const char* enumStringEmpty = "";
+
+static const char* luaEnumString_RenderStateCullFaceSide_CULL_FACE_SIDE_BACK = "CULL_FACE_SIDE_BACK";
+static const char* luaEnumString_RenderStateCullFaceSide_CULL_FACE_SIDE_FRONT = "CULL_FACE_SIDE_FRONT";
+static const char* luaEnumString_RenderStateCullFaceSide_CULL_FACE_SIDE_FRONT_AND_BACK = "CULL_FACE_SIDE_FRONT_AND_BACK";
+
+RenderState::CullFaceSide lua_enumFromString_RenderStateCullFaceSide(const char* s)
+{
+    if (strcmp(s, luaEnumString_RenderStateCullFaceSide_CULL_FACE_SIDE_BACK) == 0)
+        return RenderState::CULL_FACE_SIDE_BACK;
+    if (strcmp(s, luaEnumString_RenderStateCullFaceSide_CULL_FACE_SIDE_FRONT) == 0)
+        return RenderState::CULL_FACE_SIDE_FRONT;
+    if (strcmp(s, luaEnumString_RenderStateCullFaceSide_CULL_FACE_SIDE_FRONT_AND_BACK) == 0)
+        return RenderState::CULL_FACE_SIDE_FRONT_AND_BACK;
+    return RenderState::CULL_FACE_SIDE_BACK;
+}
+
+const char* lua_stringFromEnum_RenderStateCullFaceSide(RenderState::CullFaceSide e)
+{
+    if (e == RenderState::CULL_FACE_SIDE_BACK)
+        return luaEnumString_RenderStateCullFaceSide_CULL_FACE_SIDE_BACK;
+    if (e == RenderState::CULL_FACE_SIDE_FRONT)
+        return luaEnumString_RenderStateCullFaceSide_CULL_FACE_SIDE_FRONT;
+    if (e == RenderState::CULL_FACE_SIDE_FRONT_AND_BACK)
+        return luaEnumString_RenderStateCullFaceSide_CULL_FACE_SIDE_FRONT_AND_BACK;
+    return enumStringEmpty;
+}
+
+}

+ 15 - 0
gameplay/src/lua/lua_RenderStateCullFaceSide.h

@@ -0,0 +1,15 @@
+#ifndef LUA_RENDERSTATECULLFACESIDE_H_
+#define LUA_RENDERSTATECULLFACESIDE_H_
+
+#include "RenderState.h"
+
+namespace gameplay
+{
+
+// Lua bindings for enum conversion functions for RenderState::CullFaceSide.
+RenderState::CullFaceSide lua_enumFromString_RenderStateCullFaceSide(const char* s);
+const char* lua_stringFromEnum_RenderStateCullFaceSide(RenderState::CullFaceSide e);
+
+}
+
+#endif

+ 38 - 0
gameplay/src/lua/lua_RenderStateStateBlock.cpp

@@ -12,6 +12,7 @@
 #include "lua_RenderStateAutoBinding.h"
 #include "lua_RenderStateBlend.h"
 #include "lua_RenderStateDepthFunction.h"
+#include "lua_RenderStateCullFaceSide.h"
 
 namespace gameplay
 {
@@ -28,6 +29,7 @@ void luaRegister_RenderStateStateBlock()
         {"setBlendDst", lua_RenderStateStateBlock_setBlendDst},
         {"setBlendSrc", lua_RenderStateStateBlock_setBlendSrc},
         {"setCullFace", lua_RenderStateStateBlock_setCullFace},
+        {"setCullFaceSide", lua_RenderStateStateBlock_setCullFaceSide},
         {"setDepthFunction", lua_RenderStateStateBlock_setDepthFunction},
         {"setDepthTest", lua_RenderStateStateBlock_setDepthTest},
         {"setDepthWrite", lua_RenderStateStateBlock_setDepthWrite},
@@ -365,6 +367,42 @@ int lua_RenderStateStateBlock_setCullFace(lua_State* state)
     return 0;
 }
 
+int lua_RenderStateStateBlock_setCullFaceSide(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    //Attempt to match the parameters to a valid binding.
+    switch (paramCount) {
+        case 2:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL))
+            {
+                // Get parameter 1 off the stack.
+                RenderState::CullFaceSide param1 = (RenderState::CullFaceSide)lua_enumFromString_RenderStateCullFaceSide(luaL_checkstring(state, 2));
+
+                RenderState::StateBlock* instance = getInstance(state);
+                instance->setCullFaceSide(param1);
+
+                return 0;
+            }
+
+
+            lua_pushstring(state, "lua_RenderStateStateBlock_setCullFaceSide - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 2).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_RenderStateStateBlock_setDepthFunction(lua_State* state)
 {
     // Get the number of parameters.

+ 1 - 0
gameplay/src/lua/lua_RenderStateStateBlock.h

@@ -14,6 +14,7 @@ int lua_RenderStateStateBlock_setBlend(lua_State* state);
 int lua_RenderStateStateBlock_setBlendDst(lua_State* state);
 int lua_RenderStateStateBlock_setBlendSrc(lua_State* state);
 int lua_RenderStateStateBlock_setCullFace(lua_State* state);
+int lua_RenderStateStateBlock_setCullFaceSide(lua_State* state);
 int lua_RenderStateStateBlock_setDepthFunction(lua_State* state);
 int lua_RenderStateStateBlock_setDepthTest(lua_State* state);
 int lua_RenderStateStateBlock_setDepthWrite(lua_State* state);