【问题标题】:Examples for using Nvidia FXAA (shader antialiasing) in XNA 4.0 winforms?在 XNA 4.0 winforms 中使用 Nvidia FXAA(着色器抗锯齿)的示例?
【发布时间】:2011-10-06 20:28:02
【问题描述】:

我正在编写的应用程序中使用此示例项目的 XNA 4.0 表单控件:http://creators.xna.com/en-US/sample/winforms_series1

如果您不熟悉 FXAA,请查看创建者的网站: http://timothylottes.blogspot.com/2011/03/nvidia-fxaa.html

到目前为止,我已经花了很多时间试图弄清楚如何在没有任何运气的情况下使用它(到目前为止......)。的确,我在图形编程方面没有太多经验,但我目前确实有一个很好的应用程序正在运行,锯齿线看起来真的很糟糕。我知道 AA 的内置方法,但不适用于我和我的笔记本电脑。所以我的要求是关于使用 FXAA 而不是内置方法。

此时: 我的内容项目中有 FXAA 3.11 头文件。 我有一个由 Visual Studio 生成的通用 FX 文件,其中包含以下内容:

#define FXAA_PC_CONSOLE 1
#define FXAA_HLSL_5 1
#define FXAA_QUALITY__PRESET 12
#include "Includes/Fxaa3_11.h"

我只是在这里询问是否有人可以提供一些 XNA 4.0 示例,特别是使用该自定义 Windows 窗体方法。

感谢任何人可能提供的帮助。

编辑 3: 自从我发布此消息以来,我一直在努力研究如何让 FXAA 正常工作。 我找到了这个: http://www.gamedev.net/topic/609638-fxaa-help/page__st__20 和这个: http://fxaa-pp-inject.assembla.me/trunk/DirectX9/shader.fx

我将 FXAA 简化为 FXAA_PC_CONSOLE 类型,它可以编译。我只需要弄清楚参数 fxaaConsolePosPos 是每个像素的左上角和右下角位置。无论如何,看起来 FXAA_PC_CONSOLE 可能适用于我需要与 REACH 和基于 winforms 的 XNA 一起使用的着色器模型 2.0。

【问题讨论】:

  • 您可以选择 MLAA 吗?我认为您不会在教程中找到使用 WinForms 示例和 FXAA 的代码示例。
  • 如果它适用于较小的硬件,除了内置的抗锯齿之外的任何东西都应该是一个选项。你知道我在哪里可以找到 xna winforms MLAA 的东西吗?
  • 嗯,XNA 的任何东西(只要它不使用游戏类等)......我还没有找到任何东西,我仍在努力工作通过尽可能多地学习有关 xna 着色器的知识
  • 看看xnafinalengine.codeplex.com,他们已经实现了 MLAA,但这不是在 WinForms 环境中。
  • 感谢您的信息。我以前看过那个项目并略过它。现在的问题是它使用像素着色器版本 3,而我必须使用只能使用版本 2 的 xna“到达”渲染。

标签: xna antialiasing


【解决方案1】:

所以我想通了,至少使用了为游戏机和低端 PC 设计的 FXAA 的较小版本。我不能保证我的着色器代码参数是正确的,但是当它运行时我确实看到了明显的差异。

以下是完整的解决方案,其中包含我切碎的着色器和 C# XNA 4.0 代码片段:

首先是着色器代码(将其放在 Content 子项目的 .fx 文件中): 请注意,根据 SM2.0 不支持第一种类型的建议,我将 tex2Dlod 替换为 tex2D

#define FxaaBool bool
#define FxaaDiscard clip(-1)
#define FxaaFloat float
#define FxaaFloat2 float2
#define FxaaFloat3 float3
#define FxaaFloat4 float4
#define FxaaHalf half
#define FxaaHalf2 half2
#define FxaaHalf3 half3
#define FxaaHalf4 half4
#define FxaaSat(x) saturate(x)

#define FxaaInt2 float2
#define FxaaTex sampler2D
#define FxaaTexTop(t, p) tex2D(t, float4(p, 0.0, 0.0))
#define FxaaTexOff(t, p, o, r) tex2D(t, float4(p + (o * r), 0, 0))

FxaaFloat FxaaLuma(FxaaFloat4 rgba) { 
    rgba.w = dot(rgba.rgb, FxaaFloat3(0.299, 0.587, 0.114));
return  rgba.w; }

/*============================================================================
                         FXAA3 CONSOLE - PC VERSION
============================================================================*/
FxaaFloat4 FxaaPixelShader(
    FxaaFloat2 pos,
    FxaaFloat4 fxaaConsolePosPos,
    FxaaTex tex,
    FxaaFloat4 fxaaConsoleRcpFrameOpt,
    FxaaFloat4 fxaaConsoleRcpFrameOpt2,
    FxaaFloat fxaaConsoleEdgeSharpness,
    FxaaFloat fxaaConsoleEdgeThreshold,
    FxaaFloat fxaaConsoleEdgeThresholdMin) {
    FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy));
    FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw));
    FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy));
    FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw));
    FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy);
    #if (FXAA_GREEN_AS_LUMA == 0)
        FxaaFloat lumaM = rgbyM.w;
    #else
        FxaaFloat lumaM = rgbyM.y;
    #endif
    FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw);
    lumaNe += 1.0/384.0;
    FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw);
    FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe);
    FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe);
    FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw);
    FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw);
    FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold;
    FxaaFloat lumaMinM = min(lumaMin, lumaM);
    FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled);
    FxaaFloat lumaMaxM = max(lumaMax, lumaM);
    FxaaFloat dirSwMinusNe = lumaSw - lumaNe;
    FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM;
    FxaaFloat dirSeMinusNw = lumaSe - lumaNw;
    if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM;
    FxaaFloat2 dir;
    dir.x = dirSwMinusNe + dirSeMinusNw;
    dir.y = dirSwMinusNe - dirSeMinusNw;
    FxaaFloat2 dir1 = normalize(dir.xy);
    FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw);
    FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw);
    FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness;
    FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0);
    FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw);
    FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw);
    FxaaFloat4 rgbyA = rgbyN1 + rgbyP1;
    FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25);
    #if (FXAA_GREEN_AS_LUMA == 0)
        FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax);
    #else
        FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax);
    #endif
    if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5;
    return rgbyB; 
}
/*==========================================================================*/

uniform extern float SCREEN_WIDTH;
uniform extern float SCREEN_HEIGHT;
uniform extern texture gScreenTexture;

sampler screenSampler = sampler_state
{
    Texture = <gScreenTexture>;
    /*MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = LINEAR;
    AddressU = Clamp;
    AddressV = Clamp;*/
};

float4 PixelShaderFunction(float2 tc : TEXCOORD0) : COLOR0
{
    float pixelWidth = (1 / SCREEN_WIDTH);
    float pixelHeight = (1 / SCREEN_HEIGHT);

    float2 pixelCenter = float2(tc.x - pixelWidth, tc.y - pixelHeight);
    float4 fxaaConsolePosPos = float4(tc.x, tc.y, tc.x + pixelWidth, tc.y + pixelHeight);

    return FxaaPixelShader(
        pixelCenter,
        fxaaConsolePosPos,
        screenSampler,
        float4(-0.50 / SCREEN_WIDTH, -0.50 / SCREEN_HEIGHT, 0.50 / SCREEN_WIDTH, 0.50 / SCREEN_HEIGHT),
        float4(-2.0 / SCREEN_WIDTH, -2.0 / SCREEN_HEIGHT, 2.0 / SCREEN_WIDTH, 2.0 / SCREEN_HEIGHT),
        8.0,
        0.125,
        0.05);
}

technique ppfxaa
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}

这是应用着色器的 C-sharp 代码的 sn-p:

//..........................................
//these objects are used in managing the FXAA operation

//FXAA objects (anti-aliasing)
RenderTarget2D renderTarget;
SpriteBatch spriteBatch;
Effect fxaaAntialiasing;

//..........................................
//initialize the render target and set effect parameters

//code to handle a final antialiasing using a pixel shader
renderTarget = new RenderTarget2D(
    GraphicsDevice,
    GraphicsDevice.PresentationParameters.BackBufferWidth,
    GraphicsDevice.PresentationParameters.BackBufferHeight,
    false,
    GraphicsDevice.PresentationParameters.BackBufferFormat,
    DepthFormat.Depth24);

spriteBatch = new SpriteBatch(GraphicsDevice);
fxaaAntialiasing = content.Load<Effect>("sfxaa");
fxaaAntialiasing.CurrentTechnique = fxaaAntialiasing.Techniques["ppfxaa"];
fxaaAntialiasing.Parameters["SCREEN_WIDTH"].SetValue(renderTarget.Width);
fxaaAntialiasing.Parameters["SCREEN_HEIGHT"].SetValue(renderTarget.Height);
fxaaAntialiasing.Parameters["gScreenTexture"].SetValue(renderTarget as Texture2D);


//..........................................
//this should happen in your Draw() method

//change to our offscreen render target
GraphicsDevice.SetRenderTarget(renderTarget);
GraphicsDevice.Clear(Color.CornflowerBlue);

//
//draw all of your models and such here...
//

GraphicsDevice.SetRenderTarget(null);
GraphicsDevice.Clear(Color.Black);

//this where the shader antialiasing happens to the frame we just filled with content
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend,
    SamplerState.LinearClamp, DepthStencilState.Default, 
    RasterizerState.CullNone, fxaaAntialiasing);

//draw the buffer we made to the screen
spriteBatch.Draw(renderTarget as Texture2D, 
    new Rectangle(0, 0, renderTarget.Width, renderTarget.Height), 
    Color.White);

spriteBatch.End();

【讨论】:

  • 您好,我将尝试将 FXAA 实现为用于 WPF 项目的 PixelShader。在我正在进行的一个项目中,我有很多位图级别的操作,并希望应用像素着色器来帮助平滑锯齿状边缘。 WPF 在内置 ShaderEffect 类型中支持 PS3.0,Silverlight 支持 PS2.0。您是否有任何使用 WPF/SL 的经验,如果我在开发过程中遇到困难,您介意我问几个问题吗?
  • 对不起,我没有使用 WPF/Silverlight。基本上对于这个项目,我花了几个星期的时间来研究这个问题,因为信息太少,而且只做了足够的工作来让它工作。我想我帮不上什么忙。
  • 在最后一行 SpriteBatch.Draw(renderTarget...) 中获取异常:System.ObjectDisposedException:'无法访问已处理的对象。'有人有什么想法吗?
【解决方案2】:

我最近在我的游戏中应用了这种技术,但由于某种原因,我的边缘仍然“锯齿状”。有没有办法在某处调整代码以稍微软化锯齿状边缘?谢谢你。

【讨论】:

  • 不回答问题,请提出新问题:)
猜你喜欢
  • 2019-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多