Basado en UE4 versión 4.26
Configuración de sombreadores:
El shader escrito se coloca en esta posición del motor y se puede usar directamente en el plano del material.
Algoritmo de boceto:
- La imagen de entrada se procesa en escala de grises como imagen de fondo B.
- Copie la imagen de fondo B, invierta B y el desenfoque gaussiano para obtener la imagen de primer plano A.
- La imagen de primer plano A y la imagen de fondo B hacen una combinación de capa de sobreexposición de color.
Implementación del algoritmo:
Global.usf
return 1;
}
float4 GetKernelMeanAndVariance(float2 UV, float4 Range, float2x2 RotationMatrix)
{
float2 TexelSize = View.BufferSizeAndInvSize.zw;
float3 Mean = float3(0, 0, 0);
float3 Variance = float3(0, 0, 0);
float Samples = 0;
for (int x = Range.x; x <= Range.y; x++)
{
for (int y = Range.z; y <= Range.w; y++)
{
float2 Offset = mul(float2(x, y) * TexelSize, RotationMatrix);
float3 PixelColor = SceneTextureLookup(UV + Offset, 14, false).rgb;
Mean += PixelColor;
Variance += PixelColor * PixelColor;
Samples++;
}
}
Mean /= Samples;
Variance = Variance / Samples - Mean * Mean;
float TotalVariance = Variance.r + Variance.g + Variance.b;
return float4(Mean.r, Mean.g, Mean.b, TotalVariance);
}
float Calculate1DGaussian(float x)
{
return exp(-0.5 * pow(3.141 * (x), 2));
}
float Calculate2DGaussian(float x, float y, float sigma)
{
float part1 = 1.0 / (2.0 * PI * sigma * sigma);
float part2 = exp(-(x * x + y * y) / (2.0 * sigma * sigma));
return part1 * part2;
}
float GetPixelAngle(float2 UV)
{
float2 TexelSize = View.BufferSizeAndInvSize.zw;
float GradientX = 0;
float GradientY = 0;
float SobelX[9] = {-1, -2, -1, 0, 0, 0, 1, 2, 1};
float SobelY[9] = {-1, 0, 1, -2, 0, 2, -1, 0, 1};
int i = 0;
for (int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
// 1
float2 Offset = float2(x, y) * TexelSize;
float3 PixelColor = SceneTextureLookup(UV + Offset, 14, false).rgb;
float PixelValue = dot(PixelColor, float3(0.3,0.59,0.11));
// 2
GradientX += PixelValue * SobelX[i];
GradientY += PixelValue * SobelY[i];
i++;
}
}
return atan(GradientY / GradientX);
GaussianBlur.usf
static const int SceneTextureId = 14;
float2 TexelSize = View.ViewSizeAndInvSize.zw;
float2 UV = GetDefaultSceneTextureUV(Parameters, SceneTextureId);
float3 PixelSum = float3(0, 0, 0);
float WeightSum = 0;
for (int x = -Radius; x <= Radius; x++)
{
for (int y = -Radius; y <= Radius; y++)
{
float2 Offset = float2(x, y) * TexelSize;
float3 PixelColor = SceneTextureLookup(UV + Offset, 14, 0).rgb;
float AverageColor = (PixelColor.r + PixelColor.g + PixelColor.b)/3.0;
PixelColor.r = 1- AverageColor;
PixelColor.g = 1- AverageColor;
PixelColor.b = 1- AverageColor;
// float Weight = Calculate1DGaussian(x / Radius) * Calculate1DGaussian(y / Radius);
float Weight = Calculate2DGaussian(x, y, Sigma);
PixelSum += PixelColor * Weight;
WeightSum += Weight;
}
}
return PixelSum / WeightSum;
Efecto de boceto:
Artículo de referencia:
Uno de los algoritmos de combinación de capas de PS ( opacidad , multiplicación, sobreexposición de color, sobreexposición de color) Filtro PS - Algoritmo de boceto (1) Este artículo usa Python para implementar los efectos de boceto en filtros PS. Para conocer los principios y efectos específicos del algoritmo, consulte el blog anterior: http://blog.csdn.net/matrix_space/article /details/38687427from skimage import img_as_floatimport matplotlib.pyplot as pltfrom skimage import iofrom skim https://chenjunkai. blog.csdn.net/article/details/78345460 Filtro PS - Algoritmo de boceto (2)_Matrix_11's Blog-CSDN Blog_ El algoritmo de efecto de boceto utiliza otro algoritmo para completar la generación de efectos de boceto. https://chenjunkai.blog.csdn.net/article/details/38709605 Algoritmo de desenfoque gaussiano: registro de red de Ruan Yifenghttp://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html Una introducción detallada al desenfoque gaussiano y la implementación del código python. ¡Lea atentamente! https://blog.csdn.net/jkhere/article/details/9464701