Skip to content

Commit

Permalink
- Added diagonal pattern processing.
Browse files Browse the repository at this point in the history
- Optimized neighborhood blending pass, by only blending with the best match.
- Added shader presets: low, medium, high and ultra.
  • Loading branch information
iryoku committed Sep 1, 2011
1 parent 1c65846 commit 4265668
Show file tree
Hide file tree
Showing 16 changed files with 2,235 additions and 721 deletions.
124 changes: 91 additions & 33 deletions Demo/DX10/Code/Demo.cpp
Expand Up @@ -81,18 +81,21 @@ struct {
} commandlineOptions = {0.1f, 8, L"", L""};


#define IDC_TOGGLEFULLSCREEN 1
#define IDC_CHANGEDEVICE 2
#define IDC_LOADIMAGE 3
#define IDC_DETECTIONMODE 4
#define IDC_VIEWMODE 5
#define IDC_INPUT 6
#define IDC_ANTIALIASING 7
#define IDC_PROFILE 8
#define IDC_MAXSEARCHSTEPS_LABEL 9
#define IDC_MAXSEARCHSTEPS 10
#define IDC_THRESHOLD_LABEL 11
#define IDC_THRESHOLD 12
#define IDC_TOGGLEFULLSCREEN 1
#define IDC_CHANGEDEVICE 2
#define IDC_LOADIMAGE 3
#define IDC_INPUT 4
#define IDC_VIEWMODE 5
#define IDC_PRESET 6
#define IDC_DETECTIONMODE 7
#define IDC_ANTIALIASING 8
#define IDC_PROFILE 9
#define IDC_THRESHOLD_LABEL 10
#define IDC_THRESHOLD 11
#define IDC_MAXSEARCHSTEPS_LABEL 12
#define IDC_MAXSEARCHSTEPS 13
#define IDC_MAXDIAGSEARCHSTEPS_LABEL 14
#define IDC_MAXDIAGSEARCHSTEPS 15


float round(float n) {
Expand Down Expand Up @@ -239,7 +242,8 @@ HRESULT CALLBACK onResizedSwapChain(ID3D10Device *device, IDXGISwapChain *swapCh

hud.SetLocation(desc->Width - (45 + HUD_WIDTH), 0);

smaa = new SMAA(device, desc->Width, desc->Height);
SMAA::Preset preset = SMAA::Preset(int(hud.GetComboBox(IDC_PRESET)->GetSelectedData()));
smaa = new SMAA(device, desc->Width, desc->Height, preset);
initSMAA();
depthStencil = new DepthStencil(device, desc->Width, desc->Height, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_R24_UNORM_X8_TYPELESS);
depthBufferRenderTarget = new RenderTarget(device, desc->Width, desc->Height, DXGI_FORMAT_R32_FLOAT);
Expand Down Expand Up @@ -275,6 +279,7 @@ void drawHud(ID3D10Device *device, float elapsedTime) {
txtHelper->DrawTextLine(DXUTGetDeviceStats());
txtHelper->DrawTextLine(L"Press 'tab' to toogle the HUD, 'a' and 'd' to quickly cycle through the images");

txtHelper->SetForegroundColor(D3DXCOLOR(1.0f, 0.5f, 0.0f, 1.0f));
if (timer->isEnabled()) {
wstringstream s;
s << setprecision(2) << std::fixed;
Expand Down Expand Up @@ -544,18 +549,32 @@ void CALLBACK onGUIEvent(UINT event, int id, CDXUTControl *control, void *contex
onResizedSwapChain(DXUTGetD3D10Device(), DXUTGetDXGISwapChain(), DXUTGetDXGIBackBufferSurfaceDesc(), NULL);
}
}
case IDC_INPUT:
if (event == EVENT_COMBOBOX_SELECTION_CHANGED) {
timer->reset();
loadImage();
resizeWindow();
onReleasingSwapChain(NULL);
onResizedSwapChain(DXUTGetD3D10Device(), DXUTGetDXGISwapChain(), DXUTGetDXGIBackBufferSurfaceDesc(), NULL);
}
break;
case IDC_VIEWMODE:
if (event == EVENT_COMBOBOX_SELECTION_CHANGED) {
if (int(hud.GetComboBox(IDC_VIEWMODE)->GetSelectedData()) > 0) {
hud.GetCheckBox(IDC_ANTIALIASING)->SetChecked(true);
}
}
break;
case IDC_INPUT:
case IDC_PRESET:
if (event == EVENT_COMBOBOX_SELECTION_CHANGED) {
timer->reset();
loadImage();
resizeWindow();
SMAA::Preset selected;
selected = SMAA::Preset(int(hud.GetComboBox(IDC_PRESET)->GetSelectedData()));
hud.GetStatic(IDC_MAXSEARCHSTEPS_LABEL)->SetVisible(selected == SMAA::PRESET_CUSTOM);
hud.GetSlider(IDC_MAXSEARCHSTEPS)->SetVisible(selected == SMAA::PRESET_CUSTOM);
hud.GetStatic(IDC_MAXDIAGSEARCHSTEPS_LABEL)->SetVisible(selected == SMAA::PRESET_CUSTOM);
hud.GetSlider(IDC_MAXDIAGSEARCHSTEPS)->SetVisible(selected == SMAA::PRESET_CUSTOM);
hud.GetStatic(IDC_THRESHOLD_LABEL)->SetVisible(selected == SMAA::PRESET_CUSTOM);
hud.GetSlider(IDC_THRESHOLD)->SetVisible(selected == SMAA::PRESET_CUSTOM);
onReleasingSwapChain(NULL);
onResizedSwapChain(DXUTGetD3D10Device(), DXUTGetDXGISwapChain(), DXUTGetDXGIBackBufferSurfaceDesc(), NULL);
}
Expand All @@ -572,6 +591,20 @@ void CALLBACK onGUIEvent(UINT event, int id, CDXUTControl *control, void *contex
timer->setEnabled(hud.GetCheckBox(IDC_PROFILE)->GetChecked());
}
break;
case IDC_THRESHOLD:
if (event == EVENT_SLIDER_VALUE_CHANGED) {
CDXUTSlider *slider = (CDXUTSlider *) control;
int min, max;
slider->GetRange(min, max);

float scale = float(slider->GetValue()) / (max - min);
smaa->setThreshold(scale * 0.5f);

wstringstream s;
s << L"Threshold: " << scale * 0.5f;
hud.GetStatic(IDC_THRESHOLD_LABEL)->SetText(s.str().c_str());
}
break;
case IDC_MAXSEARCHSTEPS:
if (event == EVENT_SLIDER_VALUE_CHANGED) {
CDXUTSlider *slider = (CDXUTSlider *) control;
Expand All @@ -586,18 +619,18 @@ void CALLBACK onGUIEvent(UINT event, int id, CDXUTControl *control, void *contex
hud.GetStatic(IDC_MAXSEARCHSTEPS_LABEL)->SetText(s.str().c_str());
}
break;
case IDC_THRESHOLD:
case IDC_MAXDIAGSEARCHSTEPS:
if (event == EVENT_SLIDER_VALUE_CHANGED) {
CDXUTSlider *slider = (CDXUTSlider *) control;
int min, max;
slider->GetRange(min, max);

float scale = float(slider->GetValue()) / (max - min);
smaa->setThreshold(scale * 0.5f);
smaa->setMaxSearchStepsDiag(int(round(scale * 20.0f)));

wstringstream s;
s << L"Threshold: " << scale * 0.5f;
hud.GetStatic(IDC_THRESHOLD_LABEL)->SetText(s.str().c_str());
s << L"Max Diag. Search Steps: " << int(round(scale * 20.0f));
hud.GetStatic(IDC_MAXDIAGSEARCHSTEPS_LABEL)->SetText(s.str().c_str());
}
break;
default:
Expand All @@ -616,16 +649,8 @@ void initApp() {
hud.AddButton(IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 35, iY, HUD_WIDTH, 22);
hud.AddButton(IDC_CHANGEDEVICE, L"Change device", 35, iY += 24, HUD_WIDTH, 22, VK_F2);
hud.AddButton(IDC_LOADIMAGE, L"Load image", 35, iY += 24, HUD_WIDTH, 22);

hud.AddComboBox(IDC_DETECTIONMODE, 35, iY += 24, HUD_WIDTH, 22, 0, false);
hud.GetComboBox(IDC_DETECTIONMODE)->AddItem(L"Luma edge det.", (LPVOID) 0);
hud.GetComboBox(IDC_DETECTIONMODE)->AddItem(L"Color edge det.", (LPVOID) 1);
hud.GetComboBox(IDC_DETECTIONMODE)->AddItem(L"Depth edge det.", (LPVOID) 2);

hud.AddComboBox(IDC_VIEWMODE, 35, iY += 24, HUD_WIDTH, 22, 0, false);
hud.GetComboBox(IDC_VIEWMODE)->AddItem(L"View image", (LPVOID) 0);
hud.GetComboBox(IDC_VIEWMODE)->AddItem(L"View edges", (LPVOID) 1);
hud.GetComboBox(IDC_VIEWMODE)->AddItem(L"View weights", (LPVOID) 2);
iY += 24;

hud.AddComboBox(IDC_INPUT, 35, iY += 24, HUD_WIDTH, 22, 0, false);
buildInputComboBox();
Expand All @@ -634,18 +659,51 @@ void initApp() {
hud.GetComboBox(IDC_INPUT)->SetSelectedByData((LPVOID) -1);
}

hud.AddComboBox(IDC_VIEWMODE, 35, iY += 24, HUD_WIDTH, 22, 0, false);
hud.GetComboBox(IDC_VIEWMODE)->AddItem(L"View image", (LPVOID) 0);
hud.GetComboBox(IDC_VIEWMODE)->AddItem(L"View edges", (LPVOID) 1);
hud.GetComboBox(IDC_VIEWMODE)->AddItem(L"View weights", (LPVOID) 2);

iY += 24;

hud.AddComboBox(IDC_PRESET, 35, iY += 24, HUD_WIDTH, 22, 0, false);
hud.GetComboBox(IDC_PRESET)->AddItem(L"SMAA Low", (LPVOID) 0);
hud.GetComboBox(IDC_PRESET)->AddItem(L"SMAA Medium", (LPVOID) 1);
hud.GetComboBox(IDC_PRESET)->AddItem(L"SMAA High", (LPVOID) 2);
hud.GetComboBox(IDC_PRESET)->AddItem(L"SMAA Ultra", (LPVOID) 3);
hud.GetComboBox(IDC_PRESET)->AddItem(L"SMAA Custom", (LPVOID) 4);
hud.GetComboBox(IDC_PRESET)->SetSelectedByData((LPVOID) 2);

hud.AddComboBox(IDC_DETECTIONMODE, 35, iY += 24, HUD_WIDTH, 22, 0, false);
hud.GetComboBox(IDC_DETECTIONMODE)->AddItem(L"Luma edge det.", (LPVOID) 0);
hud.GetComboBox(IDC_DETECTIONMODE)->AddItem(L"Color edge det.", (LPVOID) 1);
hud.GetComboBox(IDC_DETECTIONMODE)->AddItem(L"Depth edge det.", (LPVOID) 2);

hud.AddCheckBox(IDC_ANTIALIASING, L"SMAA Anti-Aliasing", 35, iY += 24, HUD_WIDTH, 22, true);
hud.AddCheckBox(IDC_PROFILE, L"Profile", 35, iY += 24, HUD_WIDTH, 22, false);

iY += 24;

wstringstream s;
s << L"Threshold: " << commandlineOptions.threshold;
hud.AddStatic(IDC_THRESHOLD_LABEL, s.str().c_str(), 35, iY += 24, HUD_WIDTH, 22);
hud.AddSlider(IDC_THRESHOLD, 35, iY += 24, HUD_WIDTH, 22, 0, 100, int(100.0f * commandlineOptions.threshold / 0.5f));
hud.GetStatic(IDC_THRESHOLD_LABEL)->SetVisible(false);
hud.GetSlider(IDC_THRESHOLD)->SetVisible(false);

s = wstringstream();
s << L"Max Search Steps: " << commandlineOptions.distance;
hud.AddStatic(IDC_MAXSEARCHSTEPS_LABEL, s.str().c_str(), 35, iY += 24, HUD_WIDTH, 22);
hud.AddSlider(IDC_MAXSEARCHSTEPS, 35, iY += 24, HUD_WIDTH, 22, 0, 100, int(100.0f * commandlineOptions.distance / 98.0f));
hud.GetStatic(IDC_MAXSEARCHSTEPS_LABEL)->SetVisible(false);
hud.GetSlider(IDC_MAXSEARCHSTEPS)->SetVisible(false);

s = wstringstream();
s << L"Threshold: " << commandlineOptions.threshold;
hud.AddStatic(IDC_THRESHOLD_LABEL, s.str().c_str(), 35, iY += 24, HUD_WIDTH, 22);
hud.AddSlider(IDC_THRESHOLD, 35, iY += 24, HUD_WIDTH, 22, 0, 100, int(100.0f * commandlineOptions.threshold / 0.5f));
s << L"Max Diag. Search Steps: " << commandlineOptions.distance;
hud.AddStatic(IDC_MAXDIAGSEARCHSTEPS_LABEL, s.str().c_str(), 35, iY += 24, HUD_WIDTH, 22);
hud.AddSlider(IDC_MAXDIAGSEARCHSTEPS, 35, iY += 24, HUD_WIDTH, 22, 0, 100, int(100.0f * commandlineOptions.distance / 20.0f));
hud.GetStatic(IDC_MAXDIAGSEARCHSTEPS_LABEL)->SetVisible(false);
hud.GetSlider(IDC_MAXDIAGSEARCHSTEPS)->SetVisible(false);
}


Expand Down
39 changes: 29 additions & 10 deletions Demo/DX10/Code/SMAA.cpp
Expand Up @@ -94,29 +94,44 @@ class ID3D10IncludeResource : public ID3D10Include {
#pragma endregion


SMAA::SMAA(ID3D10Device *device, int width, int height, const ExternalStorage &storage)
SMAA::SMAA(ID3D10Device *device, int width, int height, Preset preset, const ExternalStorage &storage)
: device(device),
maxSearchSteps(8),
preset(preset),
maxSearchSteps(16),
maxSearchStepsDiag(8),
threshold(0.1f) {
HRESULT hr;

// Setup the defines for compiling the effect.
vector<D3D10_SHADER_MACRO> defines;
stringstream s;

// Setup pixel size macro
s << "float2(1.0 / " << width << ", 1.0 / " << height << ")";
string pixelSizeText = s.str();

D3D10_SHADER_MACRO defines[3] = {
{"SMAA_PIXEL_SIZE", pixelSizeText.c_str()},
{NULL, NULL}
D3D10_SHADER_MACRO pixelSizeMacro = { "SMAA_PIXEL_SIZE", pixelSizeText.c_str() };
defines.push_back(pixelSizeMacro);

// Setup preset macro
D3D10_SHADER_MACRO presetMacros[] = {
{ "SMAA_PRESET_LOW", "1" },
{ "SMAA_PRESET_MEDIUM", "1" },
{ "SMAA_PRESET_HIGH", "1" },
{ "SMAA_PRESET_ULTRA", "1" },
{ "SMAA_PRESET_CUSTOM", "1" }
};
defines.push_back(presetMacros[int(preset)]);

D3D10_SHADER_MACRO null = { NULL, NULL };
defines.push_back(null);

/**
* IMPORTANT! Here we load and compile the SMAA effect from a *RESOURCE*
* (Yeah, we like all-in-one executables for demos =)
* In case you want it to be loaded from other place change this line accordingly.
*/
ID3D10IncludeResource includeResource;
V(D3DX10CreateEffectFromResource(GetModuleHandle(NULL), L"SMAA.fx", NULL, defines, &includeResource, "fx_4_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, device, NULL, NULL, &effect, NULL, NULL));
V(D3DX10CreateEffectFromResource(GetModuleHandle(NULL), L"SMAA.fx", NULL, &defines.front(), &includeResource, "fx_4_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, device, NULL, NULL, &effect, NULL, NULL));

// This is for rendering the typical fullscreen quad later on.
D3D10_PASS_DESC desc;
Expand All @@ -142,6 +157,7 @@ SMAA::SMAA(ID3D10Device *device, int width, int height, const ExternalStorage &s
// Create some handles for techniques and variables.
thresholdVariable = effect->GetVariableByName("threshold")->AsScalar();
maxSearchStepsVariable = effect->GetVariableByName("maxSearchSteps")->AsScalar();
maxSearchStepsDiagVariable = effect->GetVariableByName("maxSearchStepsDiag")->AsScalar();
areaTexVariable = effect->GetVariableByName("areaTex")->AsShaderResource();
searchTexVariable = effect->GetVariableByName("searchTex")->AsShaderResource();
colorTexVariable = effect->GetVariableByName("colorTex")->AsShaderResource();
Expand Down Expand Up @@ -194,8 +210,11 @@ void SMAA::go(ID3D10ShaderResourceView *edgesSRV,
device->ClearRenderTargetView(*blendRenderTarget, clearColor);

// Setup variables.
V(thresholdVariable->SetFloat(threshold));
V(maxSearchStepsVariable->SetFloat(float(maxSearchSteps)));
if (preset == PRESET_CUSTOM) {
V(thresholdVariable->SetFloat(threshold));
V(maxSearchStepsVariable->SetFloat(float(maxSearchSteps)));
V(maxSearchStepsDiagVariable->SetFloat(float(maxSearchStepsDiag)));
}
V(colorTexVariable->SetResource(srcSRV));
V(edgesTexVariable->SetResource(*edgeRenderTarget));
V(blendTexVariable->SetResource(*blendRenderTarget));
Expand Down
26 changes: 18 additions & 8 deletions Demo/DX10/Code/SMAA.h
Expand Up @@ -49,6 +49,7 @@ class SMAA {
public:
class ExternalStorage;

enum Preset { PRESET_LOW, PRESET_MEDIUM, PRESET_HIGH, PRESET_ULTRA, PRESET_CUSTOM };
enum Input { INPUT_LUMA, INPUT_COLOR, INPUT_DEPTH };

/**
Expand All @@ -62,7 +63,8 @@ class SMAA {
* By default, two render targets will be created for storing
* intermediate calculations.
*/
SMAA(ID3D10Device *device, int width, int height, const ExternalStorage &storage=ExternalStorage());
SMAA(ID3D10Device *device, int width, int height, Preset preset,
const ExternalStorage &storage=ExternalStorage());
~SMAA();

/**
Expand All @@ -87,16 +89,23 @@ class SMAA {
Input input);

/**
* Maximum length to search for patterns. Each step is two pixels wide.
* Threshold for the edge detection.
*/
float getThreshold() const { return threshold; }
void setThreshold(float threshold) { this->threshold = threshold; }

/**
* Maximum length to search for horizontal/vertical patterns. Each step
* is two pixels wide.
*/
int getMaxSearchSteps() const { return maxSearchSteps; }
void setMaxSearchSteps(int maxSearchSteps) { this->maxSearchSteps = maxSearchSteps; }

/**
* Threshold for the edge detection.
* Maximum length to search for diagonal patterns.
*/
float getThreshold() const { return threshold; }
void setThreshold(float threshold) { this->threshold = threshold; }
int getMaxSearchStepsDiag() const { return maxSearchStepsDiag; }
void setMaxSearchStepsDiag(int maxSearchStepsDiag) { this->maxSearchStepsDiag = maxSearchStepsDiag; }

/**
* These two are just for debugging purposes.
Expand Down Expand Up @@ -130,6 +139,7 @@ class SMAA {
void neighborhoodBlendingPass(ID3D10RenderTargetView *dstRTV, ID3D10DepthStencilView *dsv);

ID3D10Device *device;
Preset preset;
ID3D10Effect *effect;
Quad *quad;

Expand All @@ -142,7 +152,7 @@ class SMAA {
ID3D10ShaderResourceView *searchTexSRV;

ID3D10EffectScalarVariable *thresholdVariable;
ID3D10EffectScalarVariable *maxSearchStepsVariable;
ID3D10EffectScalarVariable *maxSearchStepsVariable, *maxSearchStepsDiagVariable;
ID3D10EffectShaderResourceVariable *areaTexVariable, *searchTexVariable,
*colorTexVariable, *colorGammaTexVariable, *depthTexVariable,
*edgesTexVariable, *blendTexVariable;
Expand All @@ -153,7 +163,7 @@ class SMAA {
*blendWeightCalculationTechnique,
*neighborhoodBlendingTechnique;

int maxSearchSteps;
int maxSearchSteps, maxSearchStepsDiag;
float threshold;
};

Expand Down
4 changes: 2 additions & 2 deletions Demo/DX10/Demo.vcxproj
Expand Up @@ -128,9 +128,9 @@
<ClCompile Include="Code\Timer.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\AreaTex.h" />
<ClInclude Include="..\..\SMAA.h" />
<ClInclude Include="..\..\SearchTex.h" />
<ClInclude Include="..\..\Textures\AreaTex.h" />
<ClInclude Include="..\..\Textures\SearchTex.h" />
<ClInclude Include="Code\Copy.h" />
<ClInclude Include="DXUT\Core\DXUT.h" />
<ClInclude Include="DXUT\Optional\DXUTcamera.h" />
Expand Down

0 comments on commit 4265668

Please sign in to comment.