gfx/blur: Reduce code duplication with shared file

A lot of the blur effects share quite a bit of code, which can be offloaded into a single include.
This commit is contained in:
Michael Fabian 'Xaymar' Dirks 2021-06-08 06:08:07 +02:00
parent 1fcd141f10
commit 5d4f88e614
7 changed files with 193 additions and 297 deletions

View file

@ -1151,6 +1151,7 @@ is_feature_enabled(FILTER_BLUR T_CHECK)
if(T_CHECK)
list(APPEND PROJECT_DATA
"data/effects/mask.effect"
"data/effects/blur/common.effect"
"data/effects/blur/box.effect"
"data/effects/blur/box-linear.effect"
"data/effects/blur/dual-filtering.effect"

View file

@ -1,17 +1,4 @@
// Parameters:
/// OBS Default
uniform float4x4 ViewProj;
/// Texture
uniform texture2d pImage;
uniform float2 pImageTexel;
/// Blur
uniform float pSize;
uniform float pSizeInverseMul;
uniform float pAngle;
uniform float2 pCenter;
uniform float2 pStepScale;
#define MAX_BLUR_SIZE 128
#include "common.effect"
// # Linear Optimization
// While the normal way is to sample every texel in the pSize, linear optimization
@ -47,37 +34,17 @@ uniform float2 pStepScale;
// faster alternatives than linear sampling with Gaussian Blur, such as
// Dual Filtering ("Dual Kawase").
// Sampler
sampler_state linearSampler {
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
MinLOD = 0;
MaxLOD = 0;
};
//------------------------------------------------------------------------------
// Defines
//------------------------------------------------------------------------------
#define MAX_BLUR_SIZE 128
// Default Vertex Shader and Data
struct VertDataIn {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
struct VertDataOut {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
VertDataOut VSDefault(VertDataIn vtx) {
VertDataOut vert_out;
vert_out.pos = mul(float4(vtx.pos.xyz, 1.0), ViewProj);
vert_out.uv = vtx.uv;
return vert_out;
}
// Blur 1 Dimensional
float4 PSBlur1D(VertDataOut vtx) : TARGET {
float4 final = pImage.Sample(linearSampler, vtx.uv);
bool is_odd = ((int(round(pSize)) % 2) == 1);
//------------------------------------------------------------------------------
// Technique: Directional / Area
//------------------------------------------------------------------------------
float4 PSBlur1D(VertexInformation vtx) : TARGET {
float4 final = pImage.Sample(LinearClampSampler, vtx.uv);
bool is_odd = ((uint(round(pSize)) % 2) == 1);
// y = yes, s = skip, b = break
// Size-> | 1| 2| 3| 4| 5| 6| 7|
@ -100,13 +67,13 @@ float4 PSBlur1D(VertDataOut vtx) : TARGET {
}
float2 nstep = (pImageTexel * pStepScale) * (n + 0.5);
final += pImage.Sample(linearSampler, vtx.uv + nstep) * 2.;
final += pImage.Sample(linearSampler, vtx.uv - nstep) * 2.;
final += pImage.Sample(LinearClampSampler, vtx.uv + nstep) * 2.;
final += pImage.Sample(LinearClampSampler, vtx.uv - nstep) * 2.;
}
if (is_odd) {
float2 nstep = (pImageTexel * pStepScale) * pSize;
final += pImage.Sample(linearSampler, vtx.uv + nstep);
final += pImage.Sample(linearSampler, vtx.uv - nstep);
final += pImage.Sample(LinearClampSampler, vtx.uv + nstep);
final += pImage.Sample(LinearClampSampler, vtx.uv - nstep);
}
final *= pSizeInverseMul;

View file

@ -1,55 +1,22 @@
// Parameters:
/// OBS Default
uniform float4x4 ViewProj;
/// Texture
uniform texture2d pImage;
uniform float2 pImageTexel;
/// Blur
uniform float pSize;
uniform float pSizeInverseMul;
uniform float pAngle;
uniform float2 pCenter;
uniform float2 pStepScale;
#include "common.effect"
//------------------------------------------------------------------------------
// Defines
//------------------------------------------------------------------------------
#define MAX_BLUR_SIZE 128
// Sampler
sampler_state linearSampler {
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
MinLOD = 0;
MaxLOD = 0;
};
// Default Vertex Shader and Data
struct VertDataIn {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
struct VertDataOut {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
VertDataOut VSDefault(VertDataIn vtx) {
VertDataOut vert_out;
vert_out.pos = mul(float4(vtx.pos.xyz, 1.0), ViewProj);
vert_out.uv = vtx.uv;
return vert_out;
}
// Blur 1 Dimensional
float4 PSBlur1D(VertDataOut vtx) : TARGET {
float4 final = pImage.Sample(linearSampler, vtx.uv);
//------------------------------------------------------------------------------
// Technique: Directional / Area
//------------------------------------------------------------------------------
float4 PSBlur1D(VertexInformation vtx) : TARGET {
float4 final = pImage.Sample(LinearClampSampler, vtx.uv);
// Loop unrolling is only possible with a fixed known maximum.
// Some compilers may unroll up to x iterations, but most will not.
for (int n = 1; n <= MAX_BLUR_SIZE; n++) {
float2 nstep = (pImageTexel * pStepScale) * n;
final += pImage.Sample(linearSampler, vtx.uv + nstep);
final += pImage.Sample(linearSampler, vtx.uv - nstep);
final += pImage.Sample(LinearClampSampler, vtx.uv + nstep);
final += pImage.Sample(LinearClampSampler, vtx.uv - nstep);
if (n >= pSize) {
break;
@ -67,28 +34,19 @@ technique Draw {
}
}
// Blur Rotation
float2 rotate(float2 pt, float angle) {
float cp = cos(angle);
float sp = sin(angle);
float sn = -sp;
return float2((pt.x * cp) + (pt.y * sn), (pt.x * sp) + (pt.y * cp));
}
float2 rotateAround(float2 pt, float2 cpt, float angle) {
return rotate(pt - cpt, angle) + cpt;
}
float4 PSRotate(VertDataOut vtx) : TARGET {
float4 final = pImage.Sample(linearSampler, vtx.uv);
//------------------------------------------------------------------------------
// Technique: Rotate
//------------------------------------------------------------------------------
float4 PSRotate(VertexInformation vtx) : TARGET {
float4 final = pImage.Sample(LinearClampSampler, vtx.uv);
float angstep = pAngle * pStepScale.x;
// Loop unrolling is only possible with a fixed known maximum.
// Some compilers may unroll up to x iterations, but most will not.
for (int n = 1; n <= MAX_BLUR_SIZE; n++) {
final += pImage.Sample(linearSampler, rotateAround(vtx.uv, pCenter, angstep * n));
final += pImage.Sample(linearSampler, rotateAround(vtx.uv, pCenter, angstep * -n));
final += pImage.Sample(LinearClampSampler, rotateAround(vtx.uv, pCenter, angstep * n));
final += pImage.Sample(LinearClampSampler, rotateAround(vtx.uv, pCenter, angstep * -n));
if (n >= pSize) {
break;
@ -106,9 +64,11 @@ technique Rotate {
}
}
// Blur Zoom
float4 PSZoom(VertDataOut vtx) : TARGET {
float4 final = pImage.Sample(linearSampler, vtx.uv);
//------------------------------------------------------------------------------
// Technique: Zoom
//------------------------------------------------------------------------------
float4 PSZoom(VertexInformation vtx) : TARGET {
float4 final = pImage.Sample(LinearClampSampler, vtx.uv);
// step is calculated from the direction relative to the center
float2 dir = normalize(vtx.uv - pCenter) * pStepScale * pImageTexel;
@ -117,8 +77,8 @@ float4 PSZoom(VertDataOut vtx) : TARGET {
// Loop unrolling is only possible with a fixed known maximum.
// Some compilers may unroll up to x iterations, but most will not.
for (int n = 1; n <= MAX_BLUR_SIZE; n++) {
final += pImage.Sample(linearSampler, vtx.uv + (dir * n) * dist);
final += pImage.Sample(linearSampler, vtx.uv + (dir * -n) * dist);
final += pImage.Sample(LinearClampSampler, vtx.uv + (dir * n) * dist);
final += pImage.Sample(LinearClampSampler, vtx.uv + (dir * -n) * dist);
if (n >= pSize) {
break;

View file

@ -0,0 +1,86 @@
// Copyright 2021 Michael Fabian Dirks <info@xaymar.com>
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//------------------------------------------------------------------------------
// Defines
//------------------------------------------------------------------------------
// Kernel size as sequential float4's.
#define KERNEL_SIZE 32
//------------------------------------------------------------------------------
// Uniforms
//------------------------------------------------------------------------------
uniform float4x4 ViewProj;
uniform texture2d pImage;
uniform float2 pImageSize;
uniform float2 pImageTexel;
uniform float2 pImageHalfTexel;
uniform float pSize;
uniform float pSizeInverseMul;
uniform float pAngle;
uniform float2 pCenter;
uniform float2 pStepScale;
uniform float4 pKernel[KERNEL_SIZE];
//------------------------------------------------------------------------------
// Structures
//------------------------------------------------------------------------------
struct VertexInformation {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
sampler_state LinearClampSampler {
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
MinLOD = 0;
MaxLOD = 0;
};
//------------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------------
VertexInformation VSDefault(VertexInformation vtx) {
vtx.pos = mul(float4(vtx.pos.xyz, 1.0), ViewProj);
return vtx;
}
float2 rotate(float2 pt, float angle) {
float cp = cos(angle);
float sp = sin(angle);
float sn = -sp;
return float2((pt.x * cp) + (pt.y * sn), (pt.x * sp) + (pt.y * cp));
}
float2 rotateAround(float2 pt, float2 cpt, float angle) {
return rotate(pt - cpt, angle) + cpt;
}
float kernelAt(uint i) {
return ((float[4])(pKernel[floor(i/4)]))[i%4];
}

View file

@ -1,48 +1,16 @@
// Parameters:
/// OBS Default
uniform float4x4 ViewProj;
/// Texture
uniform texture2d pImage;
uniform float2 pImageSize;
uniform float2 pImageTexel;
uniform float2 pImageHalfTexel;
#include "common.effect"
// Sampler
sampler_state linearSampler {
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
MinLOD = 0;
MaxLOD = 0;
};
// Default Vertex Shader and Data
struct VertDataIn {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
struct VertDataOut {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
VertDataOut VSDefault(VertDataIn vtx) {
VertDataOut vert_out;
vert_out.pos = mul(float4(vtx.pos.xyz, 1.0), ViewProj);
vert_out.uv = vtx.uv;
return vert_out;
}
// Downsample
float4 PSDown(VertDataOut vtx) : TARGET {
//------------------------------------------------------------------------------
// Technique: Down
//------------------------------------------------------------------------------
float4 PSDown(VertexInformation vtx) : TARGET {
//vtx.uv = ((floor(vtx.uv * pImageSize) + float2(0.5, 0.5)) * pImageTexel);
float4 pxCC = pImage.Sample(linearSampler, vtx.uv) * 4.0;
float4 pxTL = pImage.Sample(linearSampler, vtx.uv - pImageHalfTexel);
float4 pxTR = pImage.Sample(linearSampler, vtx.uv + pImageHalfTexel);
float4 pxBL = pImage.Sample(linearSampler, vtx.uv + float2(pImageHalfTexel.x, -pImageHalfTexel.y));
float4 pxBR = pImage.Sample(linearSampler, vtx.uv - float2(pImageHalfTexel.x, -pImageHalfTexel.y));
float4 pxCC = pImage.Sample(LinearClampSampler, vtx.uv) * 4.0;
float4 pxTL = pImage.Sample(LinearClampSampler, vtx.uv - pImageHalfTexel);
float4 pxTR = pImage.Sample(LinearClampSampler, vtx.uv + pImageHalfTexel);
float4 pxBL = pImage.Sample(LinearClampSampler, vtx.uv + float2(pImageHalfTexel.x, -pImageHalfTexel.y));
float4 pxBR = pImage.Sample(LinearClampSampler, vtx.uv - float2(pImageHalfTexel.x, -pImageHalfTexel.y));
return (pxCC + pxTL + pxTR + pxBL + pxBR) * 0.125;
}
@ -54,18 +22,20 @@ technique Down {
}
}
// Upsample
float4 PSUp(VertDataOut vtx) : TARGET {
//------------------------------------------------------------------------------
// Technique: Up
//------------------------------------------------------------------------------
float4 PSUp(VertexInformation vtx) : TARGET {
//vtx.uv = ((floor(vtx.uv * pImageSize) + float2(0.5, 0.5)) * pImageTexel);
float4 pxL = pImage.Sample(linearSampler, vtx.uv - float2(pImageHalfTexel.x * 2.0, 0.));
float4 pxBL = pImage.Sample(linearSampler, vtx.uv - float2(pImageHalfTexel.x, -pImageHalfTexel.y));
float4 pxB = pImage.Sample(linearSampler, vtx.uv + float2(0., pImageHalfTexel.y * 2.0));
float4 pxBR = pImage.Sample(linearSampler, vtx.uv + pImageHalfTexel);
float4 pxR = pImage.Sample(linearSampler, vtx.uv + float2(pImageHalfTexel.x * 2.0, 0.));
float4 pxTR = pImage.Sample(linearSampler, vtx.uv + float2(pImageHalfTexel.x, -pImageHalfTexel.y));
float4 pxT = pImage.Sample(linearSampler, vtx.uv - float2(0., pImageHalfTexel.y * 2.0));
float4 pxTL = pImage.Sample(linearSampler, vtx.uv - pImageHalfTexel);
float4 pxL = pImage.Sample(LinearClampSampler, vtx.uv - float2(pImageHalfTexel.x * 2.0, 0.));
float4 pxBL = pImage.Sample(LinearClampSampler, vtx.uv - float2(pImageHalfTexel.x, -pImageHalfTexel.y));
float4 pxB = pImage.Sample(LinearClampSampler, vtx.uv + float2(0., pImageHalfTexel.y * 2.0));
float4 pxBR = pImage.Sample(LinearClampSampler, vtx.uv + pImageHalfTexel);
float4 pxR = pImage.Sample(LinearClampSampler, vtx.uv + float2(pImageHalfTexel.x * 2.0, 0.));
float4 pxTR = pImage.Sample(LinearClampSampler, vtx.uv + float2(pImageHalfTexel.x, -pImageHalfTexel.y));
float4 pxT = pImage.Sample(LinearClampSampler, vtx.uv - float2(0., pImageHalfTexel.y * 2.0));
float4 pxTL = pImage.Sample(LinearClampSampler, vtx.uv - pImageHalfTexel);
return (((pxTL + pxTR + pxBL + pxBR) * 2.0) + pxL + pxR + pxT + pxB) * 0.083333333333;
// return (((pxTL + pxTR + pxBL + pxBR) * 2.0) + pxL + pxR + pxT + pxB) / 12;

View file

@ -1,18 +1,4 @@
// Parameters:
/// OBS Default
uniform float4x4 ViewProj;
/// Texture
uniform texture2d pImage;
uniform float2 pImageTexel;
/// Blur
uniform float pSize;
uniform float pAngle;
uniform float2 pCenter;
uniform float2 pStepScale;
/// Gaussian
uniform float4 pKernel[32];
#define MAX_BLUR_SIZE 128
#include "common.effect"
// # Linear Optimization
// While the normal way is to sample every texel in the pSize, linear optimization
@ -53,41 +39,16 @@ uniform float4 pKernel[32];
// faster alternatives than linear sampling with Gaussian Blur, such as
// Dual Filtering ("Dual Kawase").
// Sampler
sampler_state linearSampler {
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
MinLOD = 0;
MaxLOD = 0;
};
//------------------------------------------------------------------------------
// Defines
//------------------------------------------------------------------------------
#define MAX_BLUR_SIZE 128
// Default Vertex Shader and Data
struct VertDataIn {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
struct VertDataOut {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
VertDataOut VSDefault(VertDataIn vtx) {
VertDataOut vert_out;
vert_out.pos = mul(float4(vtx.pos.xyz, 1.0), ViewProj);
vert_out.uv = vtx.uv;
return vert_out;
}
// Functions
float GetKernelAt(int i) {
return ((float[4])(pKernel[floor(i/4)]))[i%4];
}
// Blur 1 Dimensional
float4 PSBlur1D(VertDataOut vtx) : TARGET {
float4 final = pImage.Sample(linearSampler, vtx.uv) * GetKernelAt(0);
//------------------------------------------------------------------------------
// Technique: Directional / Area
//------------------------------------------------------------------------------
float4 PSBlur1D(VertexInformation vtx) : TARGET {
float4 final = pImage.Sample(LinearClampSampler, vtx.uv) * GetKernelAt(0);
bool is_odd = ((int(round(pSize)) % 2) == 1);
// y = yes, s = skip, b = break
@ -112,15 +73,15 @@ float4 PSBlur1D(VertDataOut vtx) : TARGET {
// TODO: Determine better position than 0.5 for gaussian approximation.
float2 nstep = (pImageTexel * pStepScale) * (n + 0.5);
float kernel = GetKernelAt(n) + GetKernelAt(n + 1);
final += pImage.Sample(linearSampler, vtx.uv + nstep) * kernel;
final += pImage.Sample(linearSampler, vtx.uv - nstep) * kernel;
float kernel = kernelAt(n) + kernelAt(n + 1);
final += pImage.Sample(LinearClampSampler, vtx.uv + nstep) * kernel;
final += pImage.Sample(LinearClampSampler, vtx.uv - nstep) * kernel;
}
if (is_odd) {
float kernel = GetKernelAt(pSize);
float kernel = kernelAt(pSize);
float2 nstep = (pImageTexel * pStepScale) * pSize;
final += pImage.Sample(linearSampler, vtx.uv + nstep) * kernel;
final += pImage.Sample(linearSampler, vtx.uv - nstep) * kernel;
final += pImage.Sample(LinearClampSampler, vtx.uv + nstep) * kernel;
final += pImage.Sample(LinearClampSampler, vtx.uv - nstep) * kernel;
}
return final;

View file

@ -1,63 +1,23 @@
// Parameters:
/// OBS Default
uniform float4x4 ViewProj;
/// Texture
uniform texture2d pImage;
uniform float2 pImageTexel;
/// Blur
uniform float pSize;
uniform float pAngle;
uniform float2 pCenter;
uniform float2 pStepScale;
/// Gaussian
uniform float4 pKernel[32];
#include "common.effect"
//------------------------------------------------------------------------------
// Defines
//------------------------------------------------------------------------------
#define MAX_BLUR_SIZE 128
// Sampler
sampler_state linearSampler {
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
MinLOD = 0;
MaxLOD = 0;
};
// Default Vertex Shader and Data
struct VertDataIn {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
struct VertDataOut {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
VertDataOut VSDefault(VertDataIn vtx) {
VertDataOut vert_out;
vert_out.pos = mul(float4(vtx.pos.xyz, 1.0), ViewProj);
vert_out.uv = vtx.uv;
return vert_out;
}
// Functions
float GetKernelAt(int i) {
return ((float[4])(pKernel[floor(i/4)]))[i%4];
}
// Blur 1 Dimensional
float4 PSBlur1D(VertDataOut vtx) : TARGET {
float4 final = pImage.Sample(linearSampler, vtx.uv)
* GetKernelAt(0);
//------------------------------------------------------------------------------
// Technique: Directional / Area
//------------------------------------------------------------------------------
float4 PSBlur1D(VertexInformation vtx) : TARGET {
float4 final = pImage.Sample(LinearClampSampler, vtx.uv) * kernelAt(0);
// Loop unrolling is only possible with a fixed known maximum.
// Some compilers may unroll up to x iterations, but most will not.
for (int n = 1; n <= MAX_BLUR_SIZE; n++) {
float2 nstep = (pImageTexel * pStepScale) * n;
float kernel = GetKernelAt(n);
final += pImage.Sample(linearSampler, vtx.uv + nstep) * kernel;
final += pImage.Sample(linearSampler, vtx.uv - nstep) * kernel;
float kernel = kernelAt(n);
final += pImage.Sample(LinearClampSampler, vtx.uv + nstep) * kernel;
final += pImage.Sample(LinearClampSampler, vtx.uv - nstep) * kernel;
if (n >= pSize) {
break;
@ -74,30 +34,20 @@ technique Draw {
}
}
// Blur Rotation
float2 rotate(float2 pt, float angle) {
float cp = cos(angle);
float sp = sin(angle);
float sn = -sp;
return float2((pt.x * cp) + (pt.y * sn), (pt.x * sp) + (pt.y * cp));
}
float2 rotateAround(float2 pt, float2 cpt, float angle) {
return rotate(pt - cpt, angle) + cpt;
}
float4 PSRotate(VertDataOut vtx) : TARGET {
float4 final = pImage.Sample(linearSampler, vtx.uv)
* GetKernelAt(0);
//------------------------------------------------------------------------------
// Technique: Rotate
//------------------------------------------------------------------------------
float4 PSRotate(VertexInformation vtx) : TARGET {
float4 final = pImage.Sample(LinearClampSampler, vtx.uv) * kernelAt(0);
float angstep = pAngle * pStepScale.x;
// Loop unrolling is only possible with a fixed known maximum.
// Some compilers may unroll up to x iterations, but most will not.
for (int n = 1; n <= MAX_BLUR_SIZE; n++) {
float kernel = GetKernelAt(n);
final += pImage.Sample(linearSampler, rotateAround(vtx.uv, pCenter, angstep * n)) * kernel;
final += pImage.Sample(linearSampler, rotateAround(vtx.uv, pCenter, angstep * -n)) * kernel;
float kernel = kernelAt(n);
final += pImage.Sample(LinearClampSampler, rotateAround(vtx.uv, pCenter, angstep * n)) * kernel;
final += pImage.Sample(LinearClampSampler, rotateAround(vtx.uv, pCenter, angstep * -n)) * kernel;
if (n >= pSize) {
break;
@ -114,10 +64,11 @@ technique Rotate {
}
}
// Blur Zoom
float4 PSZoom(VertDataOut vtx) : TARGET {
float4 final = pImage.Sample(linearSampler, vtx.uv)
* GetKernelAt(0);
//------------------------------------------------------------------------------
// Technique: Zoom
//------------------------------------------------------------------------------
float4 PSZoom(VertexInformation vtx) : TARGET {
float4 final = pImage.Sample(LinearClampSampler, vtx.uv) * kernelAt(0);
// step is calculated from the direction relative to the center
float2 dir = normalize(vtx.uv - pCenter) * pStepScale * pImageTexel;
@ -126,9 +77,9 @@ float4 PSZoom(VertDataOut vtx) : TARGET {
// Loop unrolling is only possible with a fixed known maximum.
// Some compilers may unroll up to x iterations, but most will not.
for (int n = 1; n <= MAX_BLUR_SIZE; n++) {
float kernel = GetKernelAt(n);
final += pImage.Sample(linearSampler, vtx.uv + (dir * n) * dist) * kernel;
final += pImage.Sample(linearSampler, vtx.uv - (dir * n) * dist) * kernel;
float kernel = kernelAt(n);
final += pImage.Sample(LinearClampSampler, vtx.uv + (dir * n) * dist) * kernel;
final += pImage.Sample(LinearClampSampler, vtx.uv - (dir * n) * dist) * kernel;
if (n >= pSize) {
break;