Примеры использования Nvidia FXAA (сглаживание шейдеров) в winforms XNA 4.0?

#xna #antialiasing

#xna #сглаживание

Вопрос:

Я использую элемент управления формой 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 в моем проекте контента. У меня есть общий файл FX, созданный Visual Studio, с несколькими вещами, такими как:

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

Я просто прошу здесь посмотреть, может ли кто-нибудь предоставить несколько примеров XNA 4.0, в частности, с использованием этого пользовательского метода Windows forms.

Я ценю любую помощь, которую кто-то может оказать.

Редактировать 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 может работать с шейдерной моделью 2.0, которую мне нужно использовать с XNA на основе REACH и winforms.

Комментарии:

1. Подходит ли вам MLAA? Я не думаю, что вы найдете пример кода с использованием примера WinForms плюс FXAA в учебном пособии.

2. Все, что угодно, кроме встроенного сглаживания, должно быть опцией, если оно работает на меньшем оборудовании. Знаете ли вы, где я мог бы найти что-нибудь для xna winforms в MLAA?

3. Ну, на самом деле что-нибудь с XNA вообще (если оно не использует класс game и тому подобное)… Я еще ничего не нашел и все еще пытаюсь разобраться в этом сам, изучая как можно больше о шейдерах xna

4. Взгляните на xnafinalengine.codeplex.com , поскольку они внедрили MLAA, но это не в среде WinForms.

5. Спасибо за информацию. Я видел этот проект раньше и просмотрел его. Проблема с ним прямо сейчас заключается в том, что он использует пиксельный шейдер версии 3, и я должен использовать рендеринг xna «reach», который может использовать только версию 2.

Ответ №1:

Итак, я понял это, по крайней мере, используя меньшую версию FXAA, разработанную для консолей и недорогих ПК. Я не могу гарантировать, что мои параметры для кода шейдера верны, но я вижу заметную разницу, когда он запущен.

Вот полное решение с моим нарезанным шейдером и фрагментами кода C # XNA 4.0:

Сначала код шейдера (поместите его в файл .fx в вашем подпроекте контента): обратите внимание, что я заменил tex2Dlod на tex2D в соответствии с предположением, что SM2.0 не поддерживает первый тип

 #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 для применения шейдера:

 //..........................................
//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();
  

Комментарии:

1. Привет, я собираюсь попытаться реализовать FXAA в качестве пиксельного шейдера для использования в проектах WPF. В проекте я работаю, у меня есть большое растровое изображение уровне манипуляций и хотите применить pixelshader, чтобы помочь с сглаживая неровные края. WPF поддерживает PS3.0, а Silverlight поддерживает PS2.0 со встроенным типом ShaderEffect. Есть ли у вас какой-либо опыт работы с WPF / SL и не возражаете, если я задам несколько вопросов, если и когда я застряну в разработке?

2. Извините, я не использовал WPF / Silverlight. В основном для этого проекта я потратил несколько недель на изучение проблемы, потому что информации было так мало, и сделал достаточно, чтобы заставить ее работать. Я не думаю, что мог бы сильно помочь.

3. Получение исключения в SpriteBatch предыдущей строки. Draw(RenderTarget …): Система. Исключение ObjectDisposedException: «Невозможно получить доступ к удаленному объекту». Есть идеи у кого-нибудь?

Ответ №2:

Я недавно внедрил эту технику в свою игру, но по какой-то причине мои края все еще остаются «неровными». Есть ли способ где-нибудь изменить код, чтобы немного смягчить неровные края? Спасибо.

Комментарии:

1. Не отвечая на вопрос, пожалуйста, задайте новый 🙂