MysteryX
21st June 2016, 10:41
I'm trying to implement Ordered Dithering into AviSynthShader.
I wrote the code to create the Bayer Matrix, trimming the 32x32 matrix from MPC-HC's source code at 16x16 and copying each value into the B and G fields of a BGRA texture (does the order between both byte fields matter?)
#include "Dither.h"
// Dither matrix in 16-bit floating point format
const unsigned short DITHER_MATRIX[DITHER_MATRIX_SIZE][DITHER_MATRIX_SIZE] = {
0x2c90, 0x38f4, 0x3bba, 0x29e0, 0x35f4, 0x3230, 0x3bbc, 0x3924, 0x3a46, 0x3644, 0x39e2, 0x370c, 0x3444, 0x3b1a, 0x3140, 0x39d2,
0x385a, 0x3b24, 0x2c10, 0x38c6, 0x3808, 0x2780, 0x3bbe, 0x37f8, 0x350c, 0x3a6c, 0x3368, 0x3bc0, 0x3000, 0x3886, 0x31b0, 0x3554,
0x3a94, 0x3618, 0x3430, 0x3a34, 0x3834, 0x39fe, 0x2740, 0x3758, 0x3494, 0x3b7a, 0x2700, 0x3958, 0x3858, 0x3a24, 0x364c, 0x3bc2,
0x3278, 0x3a22, 0x353c, 0x39de, 0x3268, 0x3a98, 0x36fc, 0x2ed0, 0x39e0, 0x30f0, 0x381a, 0x3996, 0x35ac, 0x3af2, 0x39b8, 0x37bc,
0x3250, 0x39dc, 0x3800, 0x30e8, 0x3b42, 0x34d4, 0x3970, 0x3afe, 0x3020, 0x3898, 0x33e8, 0x3b34, 0x2e10, 0x3320, 0x391a, 0x26c0,
0x3784, 0x38de, 0x3060, 0x3b5c, 0x3600, 0x38e6, 0x3490, 0x3b2a, 0x387a, 0x365c, 0x3b3c, 0x2be0, 0x37ac, 0x33d8, 0x2680, 0x3b98,
0x38d6, 0x2a60, 0x3b7e, 0x391e, 0x36d0, 0x2fe0, 0x3812, 0x32a0, 0x3a84, 0x36b0, 0x3a50, 0x357c, 0x37dc, 0x3b68, 0x3594, 0x3aca,
0x344c, 0x3a7c, 0x3674, 0x3884, 0x2d30, 0x3a48, 0x3170, 0x398e, 0x2900, 0x3a30, 0x34bc, 0x38ea, 0x3b70, 0x3a3c, 0x3852, 0x3460,
0x3b04, 0x37a0, 0x351c, 0x2d40, 0x3a80, 0x394e, 0x3b84, 0x3614, 0x3900, 0x2b20, 0x396c, 0x31b8, 0x38ca, 0x3a0c, 0x3038, 0x385c,
0x39a2, 0x2c70, 0x3ba2, 0x3464, 0x3992, 0x36dc, 0x3bc4, 0x3580, 0x3824, 0x32d0, 0x3abc, 0x2ec0, 0x3560, 0x30f8, 0x3974, 0x3610,
0x3a12, 0x3110, 0x3aaa, 0x38a2, 0x35e4, 0x341c, 0x28c0, 0x3a02, 0x34a8, 0x3b60, 0x3790, 0x3aa2, 0x2c40, 0x346c, 0x373c, 0x3bc6,
0x32f0, 0x37e8, 0x391c, 0x3100, 0x3af6, 0x2640, 0x3868, 0x3098, 0x3b3e, 0x3944, 0x3620, 0x3870, 0x39da, 0x374c, 0x3bc8, 0x2e20,
0x3804, 0x3932, 0x3660, 0x3260, 0x3bca, 0x38ce, 0x3ade, 0x382e, 0x30a0, 0x389e, 0x33a0, 0x363c, 0x3b86, 0x3910, 0x3a58, 0x2820,
0x36a0, 0x3b28, 0x34e0, 0x3a40, 0x3768, 0x3510, 0x3a54, 0x390e, 0x36e8, 0x2ae0, 0x3bcc, 0x31a0, 0x3aa4, 0x2600, 0x38cc, 0x3400,
0x3ac4, 0x2800, 0x3b4a, 0x39ee, 0x2cc0, 0x3764, 0x31c8, 0x35cc, 0x3bb6, 0x39a8, 0x2f30, 0x3a1e, 0x3816, 0x3160, 0x35b0, 0x389a,
0x3a86, 0x3070, 0x3848, 0x2d70, 0x38ba, 0x3baa, 0x2e60, 0x3414, 0x3ae4, 0x3544, 0x3a06, 0x37fc, 0x347c, 0x36d8, 0x3b12, 0x35a4};
HRESULT __stdcall CopyDitherMatrixToSurface(InputTexture* dst, IScriptEnvironment* env) {
// Copy into BG values of BGRA texture
int TempMatrix[DITHER_MATRIX_SIZE][DITHER_MATRIX_SIZE]{ };
short* pOut;
for (int i = 0; i < DITHER_MATRIX_SIZE; ++i) {
for (int j = 0; j < DITHER_MATRIX_SIZE; ++j) {
*(short*)&TempMatrix[i][j] = DITHER_MATRIX[i][j];
}
}
HR(CopyAviSynthToBuffer((byte*)&TempMatrix, 4 * DITHER_MATRIX_SIZE, 1, DITHER_MATRIX_SIZE, DITHER_MATRIX_SIZE, dst, env));
return S_OK;
}
HRESULT __stdcall CopyAviSynthToBuffer(const byte* src, int srcPitch, int clipPrecision, int width, int height, InputTexture* dst, IScriptEnvironment* env) {
// Copies source frame into main surface buffer, or into additional input textures
RECT SrcRect;
SrcRect.top = 0;
SrcRect.left = 0;
SrcRect.right = width;
SrcRect.bottom = height;
HR(D3DXLoadSurfaceFromMemory(dst->Surface, nullptr, nullptr, src, GetD3DFormat(clipPrecision, false), srcPitch, nullptr, &SrcRect, D3DX_FILTER_NONE, 0));
return S_OK;
}
However, I don't understand the logic of the HLSL shader. Here's what I got so far.
sampler s0 : register(s0);
uniform sampler s1 : register(s1); // the Bayer Matrix texture
float4 p0 : register(c0);
float2 p1 : register(c1);
uniform float4 MatrixSize : register(c2); // width, height, 1/width, 1/height
#define width (p0[0])
#define height (p0[1])
#define px (p1[0])
#define py (p1[1])
float Bayer(float2 uv)
{
uv = uv * MatrixSize.zw;
float2 val = dot(tex2D(s1, uv).bg, float2(256.0 * 255.0, 255.0));
val = val * MatrixSize.z * MatrixSize.w;
return val;
}
// -- Main code --
float4 main(float2 tex : TEXCOORD0) : COLOR {
float4 c0 = tex2D(s0, tex);
c0.x = c0.x + 1 / Bayer(tex);
c0.y = c0.y + 1 / Bayer(tex);
c0.z = c0.z + 1 / Bayer(tex);
return c0;
}
Can someone review this code to get it to work?
Thanks
I wrote the code to create the Bayer Matrix, trimming the 32x32 matrix from MPC-HC's source code at 16x16 and copying each value into the B and G fields of a BGRA texture (does the order between both byte fields matter?)
#include "Dither.h"
// Dither matrix in 16-bit floating point format
const unsigned short DITHER_MATRIX[DITHER_MATRIX_SIZE][DITHER_MATRIX_SIZE] = {
0x2c90, 0x38f4, 0x3bba, 0x29e0, 0x35f4, 0x3230, 0x3bbc, 0x3924, 0x3a46, 0x3644, 0x39e2, 0x370c, 0x3444, 0x3b1a, 0x3140, 0x39d2,
0x385a, 0x3b24, 0x2c10, 0x38c6, 0x3808, 0x2780, 0x3bbe, 0x37f8, 0x350c, 0x3a6c, 0x3368, 0x3bc0, 0x3000, 0x3886, 0x31b0, 0x3554,
0x3a94, 0x3618, 0x3430, 0x3a34, 0x3834, 0x39fe, 0x2740, 0x3758, 0x3494, 0x3b7a, 0x2700, 0x3958, 0x3858, 0x3a24, 0x364c, 0x3bc2,
0x3278, 0x3a22, 0x353c, 0x39de, 0x3268, 0x3a98, 0x36fc, 0x2ed0, 0x39e0, 0x30f0, 0x381a, 0x3996, 0x35ac, 0x3af2, 0x39b8, 0x37bc,
0x3250, 0x39dc, 0x3800, 0x30e8, 0x3b42, 0x34d4, 0x3970, 0x3afe, 0x3020, 0x3898, 0x33e8, 0x3b34, 0x2e10, 0x3320, 0x391a, 0x26c0,
0x3784, 0x38de, 0x3060, 0x3b5c, 0x3600, 0x38e6, 0x3490, 0x3b2a, 0x387a, 0x365c, 0x3b3c, 0x2be0, 0x37ac, 0x33d8, 0x2680, 0x3b98,
0x38d6, 0x2a60, 0x3b7e, 0x391e, 0x36d0, 0x2fe0, 0x3812, 0x32a0, 0x3a84, 0x36b0, 0x3a50, 0x357c, 0x37dc, 0x3b68, 0x3594, 0x3aca,
0x344c, 0x3a7c, 0x3674, 0x3884, 0x2d30, 0x3a48, 0x3170, 0x398e, 0x2900, 0x3a30, 0x34bc, 0x38ea, 0x3b70, 0x3a3c, 0x3852, 0x3460,
0x3b04, 0x37a0, 0x351c, 0x2d40, 0x3a80, 0x394e, 0x3b84, 0x3614, 0x3900, 0x2b20, 0x396c, 0x31b8, 0x38ca, 0x3a0c, 0x3038, 0x385c,
0x39a2, 0x2c70, 0x3ba2, 0x3464, 0x3992, 0x36dc, 0x3bc4, 0x3580, 0x3824, 0x32d0, 0x3abc, 0x2ec0, 0x3560, 0x30f8, 0x3974, 0x3610,
0x3a12, 0x3110, 0x3aaa, 0x38a2, 0x35e4, 0x341c, 0x28c0, 0x3a02, 0x34a8, 0x3b60, 0x3790, 0x3aa2, 0x2c40, 0x346c, 0x373c, 0x3bc6,
0x32f0, 0x37e8, 0x391c, 0x3100, 0x3af6, 0x2640, 0x3868, 0x3098, 0x3b3e, 0x3944, 0x3620, 0x3870, 0x39da, 0x374c, 0x3bc8, 0x2e20,
0x3804, 0x3932, 0x3660, 0x3260, 0x3bca, 0x38ce, 0x3ade, 0x382e, 0x30a0, 0x389e, 0x33a0, 0x363c, 0x3b86, 0x3910, 0x3a58, 0x2820,
0x36a0, 0x3b28, 0x34e0, 0x3a40, 0x3768, 0x3510, 0x3a54, 0x390e, 0x36e8, 0x2ae0, 0x3bcc, 0x31a0, 0x3aa4, 0x2600, 0x38cc, 0x3400,
0x3ac4, 0x2800, 0x3b4a, 0x39ee, 0x2cc0, 0x3764, 0x31c8, 0x35cc, 0x3bb6, 0x39a8, 0x2f30, 0x3a1e, 0x3816, 0x3160, 0x35b0, 0x389a,
0x3a86, 0x3070, 0x3848, 0x2d70, 0x38ba, 0x3baa, 0x2e60, 0x3414, 0x3ae4, 0x3544, 0x3a06, 0x37fc, 0x347c, 0x36d8, 0x3b12, 0x35a4};
HRESULT __stdcall CopyDitherMatrixToSurface(InputTexture* dst, IScriptEnvironment* env) {
// Copy into BG values of BGRA texture
int TempMatrix[DITHER_MATRIX_SIZE][DITHER_MATRIX_SIZE]{ };
short* pOut;
for (int i = 0; i < DITHER_MATRIX_SIZE; ++i) {
for (int j = 0; j < DITHER_MATRIX_SIZE; ++j) {
*(short*)&TempMatrix[i][j] = DITHER_MATRIX[i][j];
}
}
HR(CopyAviSynthToBuffer((byte*)&TempMatrix, 4 * DITHER_MATRIX_SIZE, 1, DITHER_MATRIX_SIZE, DITHER_MATRIX_SIZE, dst, env));
return S_OK;
}
HRESULT __stdcall CopyAviSynthToBuffer(const byte* src, int srcPitch, int clipPrecision, int width, int height, InputTexture* dst, IScriptEnvironment* env) {
// Copies source frame into main surface buffer, or into additional input textures
RECT SrcRect;
SrcRect.top = 0;
SrcRect.left = 0;
SrcRect.right = width;
SrcRect.bottom = height;
HR(D3DXLoadSurfaceFromMemory(dst->Surface, nullptr, nullptr, src, GetD3DFormat(clipPrecision, false), srcPitch, nullptr, &SrcRect, D3DX_FILTER_NONE, 0));
return S_OK;
}
However, I don't understand the logic of the HLSL shader. Here's what I got so far.
sampler s0 : register(s0);
uniform sampler s1 : register(s1); // the Bayer Matrix texture
float4 p0 : register(c0);
float2 p1 : register(c1);
uniform float4 MatrixSize : register(c2); // width, height, 1/width, 1/height
#define width (p0[0])
#define height (p0[1])
#define px (p1[0])
#define py (p1[1])
float Bayer(float2 uv)
{
uv = uv * MatrixSize.zw;
float2 val = dot(tex2D(s1, uv).bg, float2(256.0 * 255.0, 255.0));
val = val * MatrixSize.z * MatrixSize.w;
return val;
}
// -- Main code --
float4 main(float2 tex : TEXCOORD0) : COLOR {
float4 c0 = tex2D(s0, tex);
c0.x = c0.x + 1 / Bayer(tex);
c0.y = c0.y + 1 / Bayer(tex);
c0.z = c0.z + 1 / Bayer(tex);
return c0;
}
Can someone review this code to get it to work?
Thanks