【问题标题】:Is there a state that needs to be reset in between shaders着色器之间是否有需要重置的状态
【发布时间】:2013-07-23 08:08:06
【问题描述】:

我刚开始使用 XNA 进行着色器,我遇到了一些我几乎没有立即理解的行为。

我创建了一个简单的场景,其中有一个带纹理的盒子和一些可供放置的地面,由一个使用重复纹理的单个带纹理的四边形组成(所以我的纹理坐标从 0,0 到 10,10 使其重复 10次)。最初,它们都使用了 BasicEffect 类。

然后我按照教程创建了我的第一个着色器并将其用于立方体 - 只不过是一个着色器,它返回坐标坐标处纹理的颜色,为我提供与以前相同的纹理立方体。

然而发生了一些奇怪的事情 - 突然间,地面大部分是纯色的,有 2 个模糊的边缘和一个角落的正确纹理实例。纹理不再重复。我将绘制立方体和地面的顺序更改为无效,仅注释掉立方体解决的问题。

然后我查看了我的着色器代码,大部分只是从教程中复制的,发现它为 AddressU 和 AddressV 指定了 Clamp。将其更改为 Wrap 修复了所有问题,但仍然给我留下了一个问题 - 为什么一个着色器的纹理环绕逻辑会影响基本着色器?这是正常的行为吗?我需要进行某种状态保存吗?或者这是否表明我的代码中可能存在另一个错误?

groundEffect.View = camera1.View; // BasicEffect
groundEffect.Projection = projection;
groundEffect.World = Matrix.CreateTranslation(0, -1.5f, 0);
groundEffect.TextureEnabled = true;
groundEffect.Texture = groundTexture;
GraphicsDevice.Indices = groundIndexBuffer;
GraphicsDevice.SetVertexBuffer(groundVertexBuffer);
foreach (EffectPass pass in groundEffect.CurrentTechnique.Passes)
{
    pass.Apply();
    GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, groundVertexBuffer.VertexCount, 0, groundIndexBuffer.IndexCount / 3); 
}


shaderEffect.Parameters["View"].SetValue(camera1.View);
shaderEffect.Parameters["Projection"].SetValue(projection);
shaderEffect.Parameters["World"].SetValue(modelPosition);
shaderEffect.Parameters["ModelTexture"].SetValue(boxTexture);
GraphicsDevice.Indices = model.IndexBuffer;
GraphicsDevice.SetVertexBuffer(model.VertexBuffer);
foreach (EffectPass pass in shaderEffect.CurrentTechnique.Passes)
{
    pass.Apply();
    GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, model.VertexBuffer.VertexCount, 0, model.IndexBuffer.IndexCount / 3);    
}

【问题讨论】:

    标签: c# xna shader xna-4.0


    【解决方案1】:

    渲染状态由四个状态对象控制:

    GraphicsDevice.BlendState
    GraphicsDevice.DepthStencilState
    GraphicsDevice.RasterizerState
    GraphicsDevice.SamplerStates[] // one for each sampler
    

    this blog post 中解释了它们在 XNA 4 中的介绍。

    所有状态更改都通过这些变量或可以在.fx 文件中设置。

    IIRC,XNA 的内置 Effect 对象不使用任何一种方法设置状态 - 尽管 SpriteBatch 可以。

    根据您提供的代码,我无法确定在您的情况下设置状态的是什么。通常我会猜想SpriteBatch 是罪魁祸首(see this blog post)——因为这经常出现。但也许它在您的shaderEffect 中。

    无论如何,在渲染之前简单地设置你想要的状态是完全合理的。以下是 3D 渲染的典型状态:

    GraphicsDevice.BlendState = BlendState.Opaque;
    GraphicsDevice.DepthStencilState = DepthStencilState.Default;
    GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
    GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-10
      相关资源
      最近更新 更多