zoukankan      html  css  js  c++  java
  • XNA中的Render State管理

    XNA中的Render State管理

    仅供个人学习使用,请勿转载,勿用于任何商业用途。

    The Problem:
           XNA中一个设计的非常不好的地方,就是把各种render state定义为RenderState类的成员,而不是枚举。在DX/MDX中,如果有一系列render state需要设置,只需要
    foreach state in renderStates
        gfxDevice.SetRenderState( stateName,stateValue);

        简单,明了。
        而同样的操作在XNA中,则要麻烦很多,你不得不”显式” 访问每一个render state成员来设置相应的值:
    gfxDevice.RenderState.XXXX = value;
    gfxDevice.RenderState.XXXX = value;
    ……

          这样的代码非糟糕,简直是在”hard code”。假如事先不确定有多少render state需要设置,如何编码呢?

    The Solution:
          解决这个问题并不困难,我希望仍然使用传统的老方法来设置状态。首先,自然是定义一系列常量,表示所有渲染状态,这里使用了一个静态类,当然替换为枚举也是一样的。

    public static class HaRenderStateId
    {
        
    //alpha state
        public const byte AlphaBlendEnable = 0;
        
    public const byte AlphaBlendOperation = 1;
        
    public const byte SourceBlend = 2;
        
    public const byte DestinationBlend = 3;
        
    public const byte AlphaDestinationBlend = 4;
        
    public const byte AlphaSourceBlend = 5;
        
    public const byte AlphaFunction = 6;
        
    public const byte AlphaTestEnable = 7;
        
    public const byte BlendFactor = 8;
        
    public const byte BlendFunction = 9;
        
    public const byte SaparateAlphaBlendEnable = 10;
        
    public const byte ReferenceAlpha = 11;

        
    //depth state
        public const byte DepthWriteEnable = 12;
        .
    }

     
          接下来,需要统一所有render state的值。这样,才能把每种render state作为相同的key-value对,放到同一个容器中。观察一下所有的render state,他们的值不外乎以下几种:枚举,int,float,bool,color. 非常幸运,他们都能用一个32位的值来表示。但是具体如何编码呢?这种情况下,C++程序员首先想到的一定是使用union。C#中虽然没有内置的union类型,但这并不妨碍我们用struct模拟union的行为:

    [StructLayout(LayoutKind.Explicit)]
    public struct HaRenderStateValue
    {
        [FieldOffset(
    0)]
        
    public int IntegerValue;

        [FieldOffset(
    0)]
        
    public float FloatValue;

        [FieldOffset(
    0)]
        
    public Color Color;

        [FieldOffset(
    0)]
        
    public bool BooleanValue;

        
    public void SetValue(int value)
        
    public void SetValue(Color value)
        
    public void SetValue(float value)
        
    public void SetValue(bool value)
    }

    public struct HaRenderState
    {
        
    public readonly byte Id;
        
    public HaRenderStateValue Value;
    }

     
        最后则是实际设置渲染状态的函数,这一步并没有什么技巧可言,只是用了一个非常长的switch把所有需要hard code的部分集中到这里。这是目前为止我能想到的最简单有效的方法,使用Dictionary也许能减少代码长度,但实际测试表明,switch有更好的性能:

     public static void SetRenderState(GraphicsDevice graphics, HaRenderState renderState)
     {
         
    switch (renderState.Id)
         {
             
    case HaRenderStateId.AlphaBlendEnable:
                 graphics.RenderState.AlphaBlendEnable 
    = renderState.Value.BooleanValue;
                 
    break;

             
    case HaRenderStateId.AlphaBlendOperation:
                 graphics.RenderState.AlphaBlendOperation 
    = (BlendFunction)renderState.Value.IntegerValue;
                 
    break;

             
    case HaRenderStateId.SourceBlend:
                 graphics.RenderState.SourceBlend 
    = (Blend)renderState.Value.IntegerValue;
                 
    break;
            
          }
    }


            扩展结束,现在可以像文章开头介绍的那样,使用循环设置所有render state,更重要的是可以随时添加或者删除集合中的render state,这样给为渲染器设计带来了非常大的便利和灵活性:

    material.AddRenderState(RenderState)
    material.RemoveRenderState(RenderState)
    ......
    material.ApplyRenderState()

    {
          foreach renderState in this.renderStates
               SetRenderState(gfxDevice,renderState)
    }

  • 相关阅读:
    mysql修改数据表名
    HDU 5742 It's All In The Mind (贪心)
    HDU 5752 Sqrt Bo (数论)
    HDU 5753 Permutation Bo (推导 or 打表找规律)
    HDU 5762 Teacher Bo (暴力)
    HDU 5754 Life Winner Bo (博弈)
    CodeForces 455C Civilization (并查集+树的直径)
    CodeForces 455B A Lot of Games (博弈论)
    CodeForces 455A Boredom (DP)
    HDU 4861 Couple doubi (数论 or 打表找规律)
  • 原文地址:https://www.cnblogs.com/clayman/p/1509707.html
Copyright © 2011-2022 走看看