我现在正在使用Mandelbrot集的DirectX 11版本。到目前为止,我所做的是创建一个带有纹理的四边形。我可以使用Pixel Shader着色点,但是由于某些原因,Pixel Shader中设置的Mandelbrot无法返回预期的结果。我用普通的C ++代码测试了逻辑,并且得到了相同的结果。知道代码有什么问题吗?我有使用Python的合适版本,并且我刚刚复制了代码,但似乎缺少了某些东西。
集合的宽度为2.5(将图像拉伸一点)。假设窗口为1024 * 960,最大迭代1000。我使用Shader Model 5.0进行了编译。它以默认设置开头]
RealStart = -2.0;
ImagStart = -1.25;
通过常量缓冲区传递
cbuffer cBuffer
{
double RealStart; 'equals -2.5 from the default view of the set
double ImagStart; 'equals -1.25 from the default view of the set
};
// Pixel Shader
float4 main(float4 position : SV_POSITION) : SV_TARGET
{
double real, imag;
double real2, imag2;
int ite = 0;
float4 CalcColor = { 1.0f , 1.0f, 1.0f, 1.0f };
'position is the position of the pixel from 1.0f to 0.0f
real = RealStart + (double) position.x / 1024 * 2.5;
imag = ImagStart + (double) position.y / 960 * 2.5;
for (int i = 0; i < 1000; i++)
{
'breaking down the complex number by its constituents
real2 = real * real;
imag2 = imag * imag;
if (real2 + imag2 > 4.0)
{
break;
}
else {
imag = 2 * real * imag + ImagStart;
real = real2 - imag2 + RealStart;
ite++;
}
}
CalcColor[0] = (float) (ite % 333) / 333 ;
CalcColor[1] = (float) (ite % 666) / 666 ;
CalcColor[2] = (float) (ite % 1000) / 1000;
return CalcColor;
}
编辑Python版本
def Mandelbrot(creal, cimag, maxNumberOfIterations):
real = creal
imag = cimag
for numberOfIterations in range(maxNumberOfIterations):
real2 = real * real
imag2 = imag * imag
if real2 + imag2 > 4.0:
return numberOfIterations
imag = 2 * real * imag + cimag
real = real2 - imag2 + creal
return maxNumberOfIterations
creal,cimag和都是像这样创建的,然后循环遍历。
realAxis = np.linspace(realStart, realStart + width, dim)
imagAxis = np.linspace(imagStart, imagStart + width, dim)
它将maxNumberOfIterations返回到二维数组,该数组用于绘制Mandelbrot集。
错误是在其他情况下也需要缩放ImagStart和RealStart。着色器中的代码已作如下修改:
cbuffer cBuffer
{
double2 C;
float2 Param;
float MaxIt;
};
// Pixel Shader
float4 main(float4 position : SV_POSITION, float2 texcoord : TEXCOORD) : SV_TARGET
{
double real, imag;
double real2, imag2;
uint ite = 0;
float4 CalcColor = { 1.0f , 1.0f, 1.0f, 1.0f };
real = C.x + ((double) texcoord.x - 0.5) * 2.0 * 2.5;
imag = C.y + ((double) texcoord.y - 0.5) * 2.0 * 2.5;
for (int i = 0; i < 100; i++)
{
real2 = real * real;
imag2 = imag * imag;
if (real2 + imag2 > 4.0)
{
break;
}
else {
imag = 2 * real * imag + C.y + ((double) texcoord.y - 0.5) * 2.0 * 2.5;
real = real2 - imag2 + C.x + ((double) texcoord.x - 0.5) * 2.0 * 2.5;
ite++;
}
}
if (ite > 100)
ite = 100;
CalcColor[0] = (float)(ite % 33) / 33;
CalcColor[1] = (float)(ite % 66) / 66;
CalcColor[2] = (float)(ite % 100) / 100;
return CalcColor;
}
正确绘制了Mandelbrot设置,但是我无法从常量缓冲区中检索“ Param”和“ MaxIt”。
CBUFFER结构看起来像这样:
struct CBUFFER
{
double rStart, iStart;
float Width, Zoom;
float MaxIt;
};
Constantbuffer的标准设置:
// define and set the constant buffer
D3D11_BUFFER_DESC bd = { 0 };
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(CBUFFER);
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
dev->CreateBuffer(&bd, nullptr, &constantbuffer);
CBUFFER cBuffer;
cBuffer.iStart = ImagStart; '-2.0
cBuffer.rStart = RealStart; '-1.25
cBuffer.Width = 2.5;
cBuffer.Zoom = 1;
cBuffer.MaxIt = Iterations; '100
devcon->UpdateSubresource(constantbuffer.Get(), 0, 0, &cBuffer, 0, 0);
// tell the GPU which texture to use
devcon->PSSetShaderResources(0, 1, texture.GetAddressOf());
任何线索为什么cBuffer中的其他参数都不可读?还有我不明白的错误。例如,如果我将Param更改为double2并相应地更改结构,则会出现错误。鉴于常量缓冲区必须打包为16个字节,因此应该可以工作。 2x8代表DoubleImageStart和RealStart = 16bytes,Param + float MaxIt(16 + 16 + 4)相同。如果我将所有内容都更改为float,则也存在相同的类型或错误,这在理论上也应该起作用。前16个字节包中有4个浮点数,第二个(16 + 4)中有1个浮点数。