在加载和保存期间,DirectX 中的 PNG 纹理缺少一些颜色?

Posted

技术标签:

【中文标题】在加载和保存期间,DirectX 中的 PNG 纹理缺少一些颜色?【英文标题】:Missing some colors from PNG texture in DirectX during loading and saving? 【发布时间】:2012-12-20 12:50:06 【问题描述】:

我使用标准 DirectX 函数(如 CreateTexture2DD3DX11SaveTextureToFileD3DX11CreateShaderResourceViewFromFile)来加载 PNG 图像,在新创建的纹理上渲染它,然后保存到文件。所有的纹理都是两种尺寸的力量。

但在此过程中,我注意到 PNG 中的一些颜色有些损坏(与源纹理中的颜色相似但不同)。透明度也是如此(它适用于 0 和 100% 透明度部分,但不适用于例如 34%)。

是否有一些大的颜色近似值或者我做错了什么?如果是这样,我该如何解决?

这是这两张图片(左边是来源:底部有一些不同的颜色和一些渐变透明度;右边是加载第一张图片并在新纹理上渲染后的图片,然后保存到文件中):

我不知道是什么导致了这种行为,也许是新纹理的描述:

textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;

我试过改成DXGI_FORMAT_R32G32B32A32_FLOAT,效果更奇怪:

这是在新纹理上渲染源纹理的代码:

context->OMSetRenderTargets(1, &renderTargetView, depthStencilView); //to render on new texture instead of the screen
float clearColor[4] = 0.0f, 0.0f, 0.0f, 0.0f; //red, green, blue, alpha
context->ClearRenderTargetView(renderTargetView, clearColor);
//clear the depth buffer to 1.0 (max depth)
context->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
//rendering
turnZBufferOff();
shader->set(context);
object->render(shader, camera, textureManager, context, 0);
swapChain->Present(0, 0);

object->render():

UINT stride;
stride = sizeof(Vertex);
UINT offset = 0;
context->IASetVertexBuffers( 0, 1, &buffers->vertexBuffer, &stride, &offset ); //set vertex buffer
context->IASetIndexBuffer( buffers->indexBuffer, DXGI_FORMAT_R16_UINT, 0 ); //set index buffer
context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); //set primitive topology

if(textureID)
    context->PSSetShaderResources( 0, 1, &textureManager->get(textureID)->texture);


ConstantBuffer2DStructure cbPerObj;
cbPerObj.positionAndScale = XMFLOAT4(center.getX(), center.getY(), halfSize.getX(), halfSize.getY());
cbPerObj.textureCoordinates =  XMFLOAT4(textureRectToUse[0].getX(), textureRectToUse[0].getY(), textureRectToUse[1].getX(), textureRectToUse[1].getY());
context->UpdateSubresource(constantBuffer, 0, NULL, &cbPerObj, 0, 0);
context->VSSetConstantBuffers(0, 1, &constantBuffer);
context->PSSetConstantBuffers(0, 1, &constantBuffer);

context->DrawIndexed(6, 0, 0);

着色器非常简单:

VS_OUTPUT VS(float4 inPos : POSITION, float2 inTexCoord : TEXCOORD)


    VS_OUTPUT output;
    output.Pos.zw = float2(0.0f, 1.0f);

    //inPos(x,y) = -1,1
    output.Pos.xy = (inPos.xy * positionAndScale.zw) + positionAndScale.xy;
    output.TexCoord.xy = inTexCoord.xy * (textureCoordinates.zw - textureCoordinates.xy) + textureCoordinates.xy;

    return output;



float4 PS(VS_OUTPUT input) : SV_TARGET

return ObjTexture.Sample(ObjSamplerState, input.TexCoord);

为了进行一些优化,我将精灵的大小解析为着色器的参数(它工作正常,纹理大小、边框等都是正确的)。

【问题讨论】:

请发布您的代码,您将源纹理渲染到第二个纹理和着色器的位置。 好吧,我希望我没有错过任何重要的部分。 【参考方案1】:

您是否设置了混合状态?默认情况下,Alpha 不起作用,因为默认混合根本没有混合。

这是一个标准的 alpha 混合状态:

    D3D11_BLEND_DESC desc;
desc.AlphaToCoverageEnable=false;
desc.IndependentBlendEnable = false;

for (int i =0; i < 8 ; i++)

    desc.RenderTarget[i].BlendEnable = true;
    desc.RenderTarget[i].BlendOp = D3D11_BLEND_OP::D3D11_BLEND_OP_ADD;
    desc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP::D3D11_BLEND_OP_ADD;
    desc.RenderTarget[i].DestBlend = D3D11_BLEND::D3D11_BLEND_INV_SRC_ALPHA;
    desc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND::D3D11_BLEND_ONE;
    desc.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE::D3D11_COLOR_WRITE_ENABLE_ALL;
    desc.RenderTarget[i].SrcBlend = D3D11_BLEND::D3D11_BLEND_SRC_ALPHA;
    desc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND::D3D11_BLEND_ONE;


ID3D11BlendState* state;
device->CreateBlendState(&desc,&state);
return state;

我也会使用 Clear 并将 alpha 分量设置为 1 而不是 0

【讨论】:

【参考方案2】:

我建议您的问题源于导入分层的 Fireworks PNG 文件。 Fireworks 分层 PNG 在导入到 Flash 和 Freehand 等其他软件时会保留其图层。但是,为了在 Photoshop 中精确复制分层的 Fireworks PNG,有必要将该分层的 PNG 导出为平面 PNG。因此,在 Photoshop 中打开它并展平它不是解决方案;解决方案在于在 Fireworks 中将其打开并展平。 (注意:PNG 可以是 8 位、24 位或 32 位...可能需要在您的分析中加以考虑。)

【讨论】:

当我在 Photoshop 中打开 PNG 时,它们位于单层上,所以我猜它们没有分层。在该程序中使用“拼合图像”选项无论如何都会删除它们的透明度。 它们不是分层的 PNG。 我想补充一点,我根本不使用 Fireworks(所以我不明白为什么它可能是“导入 Fireworks 文件的问题) - 我在 Photoshop 中创建我的 PNG 或下载它来自网络(所有这些都以相同的方式工作)。生成的 PNG(来自我的应用程序)在任何 PNG 查看器中看起来都是一样的,包括 Windows 默认图片查看器和 Photoshop。

以上是关于在加载和保存期间,DirectX 中的 PNG 纹理缺少一些颜色?的主要内容,如果未能解决你的问题,请参考以下文章

在加载/保存期间从 Simulator 目录中提取 plist 以与我的项目一起使用

纹理不适用于我的 3d Cube directX

OpenGL:加载纹理会改变当前颜色

MATLAB:保存散点图需要太长时间

iPhone保存的png在我加载回来后不一样了

DirectX11--HLSL编译着色器的三种方法