Skip to content
Permalink
Browse files

Add FXAA antialiasing on non-mobile. Works best when render resolutio…

…n = window size.
  • Loading branch information...
hrydgard committed Sep 26, 2013
1 parent 49a72a4 commit b10e2bce3c49b56bec3a9f619c300e36d17923e5
Showing with 120 additions and 16 deletions.
  1. +6 −0 Core/Config.cpp
  2. +1 −0 Core/Config.h
  3. +2 −3 Core/CoreParameter.h
  4. +29 −11 GPU/GLES/Framebuffer.cpp
  5. +2 −2 GPU/GLES/Framebuffer.h
  6. +3 −0 UI/GameSettingsScreen.cpp
  7. +68 −0 assets/shaders/fxaa.fsh
  8. +9 −0 assets/shaders/fxaa.vsh
@@ -178,6 +178,11 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename)
graphics->Get("DisableStencilTest", &bDisableStencilTest, false);
graphics->Get("AlwaysDepthWrite", &bAlwaysDepthWrite, false);
graphics->Get("LowQualitySplineBezier", &bLowQualitySplineBezier, false);
#ifdef USING_GLES2
bFXAA = false;
#else
graphics->Get("FXAA", &bFXAA, false);
#endif

IniFile::Section *sound = iniFile.GetOrCreateSection("Sound");
sound->Get("Enable", &bEnableSound, true);
@@ -338,6 +343,7 @@ void Config::Save() {
graphics->Set("DisableStencilTest", bDisableStencilTest);
graphics->Set("AlwaysDepthWrite", bAlwaysDepthWrite);
graphics->Set("LowQualitySplineBezier", bLowQualitySplineBezier);
graphics->Set("FXAA", bFXAA);

IniFile::Section *sound = iniFile.GetOrCreateSection("Sound");
sound->Set("Enable", bEnableSound);
@@ -95,6 +95,7 @@ struct Config {
bool bDisableStencilTest;
bool bAlwaysDepthWrite;
bool bLowQualitySplineBezier;
bool bFXAA;

// Sound
bool bEnableSound;
@@ -15,7 +15,6 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.


#pragma once

#include <string>
@@ -32,8 +31,8 @@ enum GPUCore {
GPU_DIRECTX9,
};

struct CoreParameter
{
// PSP_CoreParameter()
struct CoreParameter {
CoreParameter() : collectEmuLog(0), unthrottle(false), fpsLimit(0), updateRecent(true) {}
CPUCore cpuCore;
GPUCore gpuCore;
@@ -155,15 +155,33 @@ void DisableState() {
}

void FramebufferManager::CompileDraw2DProgram() {
if (!draw2dprogram) {
draw2dprogram = glsl_create_source(basic_vs, tex_fs);
if (!draw2dprogram_) {
if (g_Config.bFXAA) {
draw2dprogram_ = glsl_create("assets/shaders/fxaa.vsh", "assets/shaders/fxaa.fsh");
} else {
draw2dprogram_ = glsl_create_source(basic_vs, tex_fs);
}
glsl_bind(draw2dprogram_);
glUniform1i(draw2dprogram_->sampler0, 0);

float u_delta = 1.0f / PSP_CoreParameter().renderWidth;
float v_delta = 1.0f / PSP_CoreParameter().renderHeight;

if (g_Config.bFXAA) {
glUniform2f(glsl_uniform_loc(draw2dprogram_, "u_texcoordDelta"), u_delta, v_delta);
}

glsl_bind(draw2dprogram);
glUniform1i(draw2dprogram->sampler0, 0);
glsl_unbind();
}
}

void FramebufferManager::DestroyDraw2DProgram() {
if (draw2dprogram_) {
glsl_destroy(draw2dprogram_);
draw2dprogram_ = 0;
}
}

FramebufferManager::FramebufferManager() :
displayFramebufPtr_(0),
displayStride_(0),
@@ -176,7 +194,7 @@ FramebufferManager::FramebufferManager() :
drawPixelsTex_(0),
drawPixelsTexFormat_(GE_FORMAT_INVALID),
convBuf(0),
draw2dprogram(0)
draw2dprogram_(0)
#ifndef USING_GLES2
,
pixelBufObj_(0),
@@ -225,8 +243,8 @@ FramebufferManager::FramebufferManager() :
FramebufferManager::~FramebufferManager() {
if (drawPixelsTex_)
glDeleteTextures(1, &drawPixelsTex_);
if (draw2dprogram) {
glsl_destroy(draw2dprogram);
if (draw2dprogram_) {
glsl_destroy(draw2dprogram_);
}

#ifndef USING_GLES2
@@ -348,7 +366,7 @@ void FramebufferManager::DrawActiveTexture(float x, float y, float w, float h, b

if(!program) {
CompileDraw2DProgram();
program = draw2dprogram;
program = draw2dprogram_;
}

glsl_bind(program);
@@ -731,6 +749,7 @@ void FramebufferManager::CopyDisplayToOutput() {

if (resized_) {
ClearBuffer();
DestroyDraw2DProgram();
}

if (vfb->fbo) {
@@ -889,7 +908,7 @@ void FramebufferManager::BlitFramebuffer_(VirtualFramebuffer *src, VirtualFrameb

CompileDraw2DProgram();

DrawActiveTexture(x, y, w, h, flip, upscale, vscale, draw2dprogram);
DrawActiveTexture(x, y, w, h, flip, upscale, vscale, draw2dprogram_);

glBindTexture(GL_TEXTURE_2D, 0);
fbo_unbind();
@@ -1187,8 +1206,7 @@ void FramebufferManager::EndFrame() {

void FramebufferManager::DeviceLost() {
DestroyAllFBOs();
glsl_destroy(draw2dprogram);
draw2dprogram = 0;
DestroyDraw2DProgram();
resized_ = false;
}

@@ -174,6 +174,7 @@ class FramebufferManager {

private:
void CompileDraw2DProgram();
void DestroyDraw2DProgram();

u32 displayFramebufPtr_;
u32 displayStride_;
@@ -209,8 +210,7 @@ class FramebufferManager {
GEBufferFormat drawPixelsTexFormat_;

u8 *convBuf;
GLSLProgram *draw2dprogram;

GLSLProgram *draw2dprogram_;

TextureCache *textureCache_;
ShaderManager *shaderManager_;
@@ -119,6 +119,9 @@ void GameSettingsScreen::CreateViews() {
graphicsSettings->Add(new CheckBox(&g_Config.bHardwareTransform, gs->T("Hardware Transform")));
graphicsSettings->Add(new CheckBox(&g_Config.bVertexCache, gs->T("Vertex Cache")));
graphicsSettings->Add(new CheckBox(&g_Config.bLowQualitySplineBezier, gs->T("Low quality spline/bezier curves (speed)")));
#ifndef USING_GLES
graphicsSettings->Add(new CheckBox(&g_Config.bFXAA, gs->T("FXAA antialiasing")));
#endif

static const char *internalResolutions[] = {"Auto (1:1)", "1x PSP", "2x PSP", "3x PSP", "4x PSP", "5x PSP" };
graphicsSettings->Add(new PopupMultiChoice(&g_Config.iInternalResolution, gs->T("Rendering Resolution"), internalResolutions, 0, ARRAY_SIZE(internalResolutions), gs, screenManager()))->OnClick.Handle(this, &GameSettingsScreen::OnResolutionChange);
@@ -0,0 +1,68 @@
// PPSSPP: Grabbed from Processing and slightly modified.

// FXAA shader, GLSL code adapted from:
// http://horde3d.org/wiki/index.php5?title=Shading_Technique_-_FXAA
// Whitepaper describing the technique:
// http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

uniform sampler2D sampler0;

// The inverse of the texture dimensions along X and Y
uniform vec2 u_texcoordDelta;
varying vec4 v_texcoord0;

void main() {
// The parameters are hardcoded for now, but could be
// made into uniforms to control fromt he program.
float FXAA_SPAN_MAX = 8.0;
float FXAA_REDUCE_MUL = 1.0/8.0;
float FXAA_REDUCE_MIN = (1.0/128.0);

vec3 rgbNW = texture2D(sampler0, v_texcoord0.xy + (vec2(-1.0, -1.0) * u_texcoordDelta)).xyz;
vec3 rgbNE = texture2D(sampler0, v_texcoord0.xy + (vec2(+1.0, -1.0) * u_texcoordDelta)).xyz;
vec3 rgbSW = texture2D(sampler0, v_texcoord0.xy + (vec2(-1.0, +1.0) * u_texcoordDelta)).xyz;
vec3 rgbSE = texture2D(sampler0, v_texcoord0.xy + (vec2(+1.0, +1.0) * u_texcoordDelta)).xyz;
vec3 rgbM = texture2D(sampler0, v_texcoord0.xy).xyz;

vec3 luma = vec3(0.299, 0.587, 0.114);
float lumaNW = dot(rgbNW, luma);
float lumaNE = dot(rgbNE, luma);
float lumaSW = dot(rgbSW, luma);
float lumaSE = dot(rgbSE, luma);
float lumaM = dot( rgbM, luma);

float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));

vec2 dir;
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));

float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);

float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);

dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * u_texcoordDelta;

vec3 rgbA = (1.0/2.0) * (
texture2D(sampler0, v_texcoord0.xy + dir * (1.0/3.0 - 0.5)).xyz +
texture2D(sampler0, v_texcoord0.xy + dir * (2.0/3.0 - 0.5)).xyz);
vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (
texture2D(sampler0, v_texcoord0.xy + dir * (0.0/3.0 - 0.5)).xyz +
texture2D(sampler0, v_texcoord0.xy + dir * (3.0/3.0 - 0.5)).xyz);
float lumaB = dot(rgbB, luma);

if((lumaB < lumaMin) || (lumaB > lumaMax)){
gl_FragColor.xyz=rgbA;
} else {
gl_FragColor.xyz=rgbB;
}
gl_FragColor.a = 1.0;
}

@@ -0,0 +1,9 @@
#version 120
attribute vec4 a_position;
attribute vec2 a_texcoord0;
uniform mat4 u_viewproj;
varying vec2 v_texcoord0;
void main() {
v_texcoord0 = a_texcoord0;
gl_Position = u_viewproj * a_position;
}

12 comments on commit b10e2bc

@solarmystic

This comment has been minimized.

Copy link
Contributor

replied Sep 26, 2013

@hrydgard

FXAA doesn't seem to be working at all at the moment, in fact all I get is a white Box overlaid across a larger black screen (or just black screens) when FXAA is enabled for any game. And yes, rendering resolution has been set to the same as the window size (3x), tested with 3x Window size, with an AMD graphics card.

Specs:- Intel Core 2 Duo t9550, ATI/AMD Mobility Radeon HD 4670

capture
capture

I assumed it was a fault of a self compiled build, so I then got one off the buildbot and retested using a fresh ppsspp.ini file. Same result.

capture

@hrydgard

This comment has been minimized.

Copy link
Owner Author

replied Sep 26, 2013

nVidia here, it works fine. Hm.

@hrydgard

This comment has been minimized.

Copy link
Owner Author

replied Sep 26, 2013

in native/gfx_es2/glsl_program.cpp, can you set a breakpoint on line 22 and run in debug mode?

If it hits the breakpoint please get the value from infoLog and post it here.

@solarmystic

This comment has been minimized.

Copy link
Contributor

replied Sep 26, 2013

@hrydgard

Where can I find this "infoLog" value? I've already set a breakpoint on line 22 in the glsl_program.cpp file and I'm running the game in debug mode in MSVC 2010. And how do I know when the breakpoint is being hit? Sorry, this is rather new to me.

@solarmystic

This comment has been minimized.

Copy link
Contributor

replied Sep 26, 2013

@hrydgard

Hmm. I think I get it, it's not hitting the breakpoint in any of the games I've tested so far with FXAA enabled.

@daniel229

This comment has been minimized.

Copy link
Collaborator

replied Sep 26, 2013

Not working on GTX460v2,driver is 311.06.The screen is same as solarmystic posted.

@daniel229

This comment has been minimized.

Copy link
Collaborator

replied Sep 26, 2013

Working now,need to put shaders folder into assets folder.

@hrydgard

This comment has been minimized.

Copy link
Owner Author

replied Sep 26, 2013

uh, the shaders folder is already in the assets folder, right?

@daniel229

This comment has been minimized.

Copy link
Collaborator

replied Sep 26, 2013

Looks like the emu FXAA mixes some kinds of texture filtering,It much more blurred than nvidia panel FXAA.

emu FXAA
01

nvidia panel FXAA
02

no FXAA
03

@hrydgard

This comment has been minimized.

Copy link
Owner Author

replied Sep 26, 2013

yes, it's the simplest possible version and I didn't even start to tweak the parameters. Try messing around with the parameters in assets/shaders/fxaa.fsh if you like.

@fagoatse

This comment has been minimized.

Copy link

replied Sep 26, 2013

SMAA would be a better choice since it doesn't blur - https://github.com/iryoku/smaa

@hrydgard

This comment has been minimized.

Copy link
Owner Author

replied Sep 26, 2013

Obviously!

I just did FXAA now because it's fast and super easy to integrate, unlike SMAA which is 3-pass and requires quite a bit of infrastructure around the shaders.

Please sign in to comment.
You can’t perform that action at this time.