Blending two images together.

Started by
24 comments, last by terryeverlast 9 years, 2 months ago

Im trying to Subtract a image with blending. I made a image(brick wall) with a alpha channel(black and white image..vines)

so it is one image. Is this right. ?

Here is my code


D3D11_BLEND_DESC myBlend = { 0 };

	myBlend.AlphaToCoverageEnable = false;
	myBlend.ransparentDesc.IndependentBlendEnable = false;

	myBlend.RenderTarget[0].BlendEnable = true;
	myBlend.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
	myBlend.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
	myBlendRenderTarget[0].BlendOp = D3D11_BLEND_OP_SUBTRACT;
	myBlend.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
	myBlendRenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
	myBlend.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
	myBlend.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
	HR(md3dDevice->CreateBlendState(&myBlend &BLENDTEST));

The alpha channel is not being subtracted from the image image. It should be a brick wall with vines.

What is wrong with my code?

Advertisement

You want to render a wall and on top of it vines which are masked by the alpha channel ?

Then you need to first render the wall (solid) and alpha-blend (not substract) the vines. Try something like this:


	myBlend.RenderTarget[0].BlendEnable = true;
	myBlend.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
	myBlend.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
	myBlendRenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
	myBlend.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
	myBlendRenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
	myBlend.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
	myBlend.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
	HR(md3dDevice->CreateBlendState(&myBlend &BLENDTEST));

That blend makes the image transparent. The alpha(vines) is the transparent part.

I need something like this in the image.

2e5tpiv.jpg

One of my question is. Do I load the brick wall with that alpha into one image?

I loaded the brick wall as the rgb, and the vines as the alpha channel with the DxTex.exe.

My book says this.

Suppose that we want to Subtract the source pixels with the destination pixels. To do this, set the source blend factor to D3D11_BLEND_ONE, the destination blend factor to D3D11_BLEND_ONE, and the blend operator to D3D11_BLEND_OP_SUBTRACT.

what happens if you load the vines as RGBA instead?

I'm using a similar blend state to you, except that all my textures are RGBA and it all works fine...

I combined the brick with the vines with the tool "DirectX Texture Tool" and changed the surface format to "Four CC 8-bit DXT5" and loaded the alpha onto the the texture.

This is right?

Your problem is, that your vine value is in the alpha channel solely, because you cannot use only the alpha channel as all color components in fixed-function blending.

I can think of these solutions:

- Actually put vines into (grayscale) separate texture. Then, render the brick tex in a first pass and the vines in a second one with the same geometry and blendOp=BLEND_OP_REV_SUBTRACT, srcBlend=BLEND_ONE, dstBlend=BLEND_ONE

- Do blending in the Pixel Shader instead. There you can extract the alpha channel and subtract it from the other color components. If you have to render the vines in an extra pass, just use BLEND_OP_REV_SUBTRACT and output (a, a, a) in the Pixel shader, where a is the alpha value of the texture.

Hope i could help.

I really don't want to use the pixel shader to do this. I want to use the first option.(Multipass texturing)


 D3DX11_TECHNIQUE_DESC techDesc;
	activeTech->GetDesc( &techDesc );
    for(UINT p = 0; p < techDesc.Passes; ++p)
    {
		md3dImmediateContext->IASetVertexBuffers(0, 1, &mBoxVB, &stride, &offset);
		md3dImmediateContext->IASetIndexBuffer(mBoxIB, DXGI_FORMAT_R32_UINT, 0);

				
		// Restore default blend state
		
		// Draw the box.
		world = XMLoadFloat4x4(&mBoxWorld);
		worldInvTranspose = MathHelper::InverseTranspose(world);
		worldViewProj = world*view*proj;

		Effects::BasicFX->SetWorld(world);
		Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose);
		Effects::BasicFX->SetWorldViewProj(worldViewProj);
		Effects::BasicFX->SetTexTransform(XMMatrixIdentity());
		Effects::BasicFX->SetMaterial(mBoxMat);
		Effects::BasicFX->SetDiffuseMap(mDiffuseMapSRV6);
		
		md3dImmediateContext->OMSetBlendState(TransparentBS, blendFactor, 0xffffffff);
		activeTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
		Effects::BasicFX->SetDiffuseMap(mDiffuseMapSRV7);
		activeTech->GetPassByIndex(p)->Apply(1, md3dImmediateContext);
		md3dImmediateContext->DrawIndexed(mBoxIndexCount, mBoxIndexOffset, mBoxVertexOffset);
		md3dImmediateContext->OMSetBlendState(0, blendFactor, 0xffffffff);
		
				
    }

	HR(mSwapChain->Present(0, 0));
}

I tried that, but not working

Well the principle of multipass rendering is that you set some drawing information (blend state, texture maps/DiffuseMap, Transformation), render a geometry (DrawIndexed), set some other draw information and render the geometry again.

You don't really need Effect passes for that. Just set a different texture and blendstate, then render the geometry. Do this twice.

0. Set transformation, VBs and IBs. (Btw: 16Bit / R16 Index Bufers are often enough and save half of the data)

1. Set opaque blend state (BlendEnable=FALSE) and your brick texture

2. DrawIndexed()

3. Set "transparent" BS (srcBlend=ONE, dstBlend=ONE, blendOp=BLEND_OP_REV_SUBTRACT) and your vines texture

4. DrawIndexed()

Got a change but not the exact thing I need

here is what I got

1073laq.jpg

I see the alpha with some brown from the bricks..but where is the bricks?

The image should be like

2e5tpiv.jpg


// Draw the box.
		world = XMLoadFloat4x4(&mBoxWorld);
		worldInvTranspose = MathHelper::InverseTranspose(world);
		worldViewProj = world*view*proj;

		Effects::BasicFX->SetWorld(world);
		Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose);
		Effects::BasicFX->SetWorldViewProj(worldViewProj);
		Effects::BasicFX->SetTexTransform(XMMatrixIdentity());
		Effects::BasicFX->SetMaterial(mBoxMat);
		Effects::BasicFX->SetDiffuseMap(mDiffuseMapSRV6);
		
		md3dImmediateContext->OMSetBlendState(TransparentBS, blendFactor, 0xffffffff);
		
		md3dImmediateContext->DrawIndexed(mBoxIndexCount, mBoxIndexOffset, mBoxVertexOffset);
		Effects::BasicFX->SetDiffuseMap(mDiffuseMapSRV7);
		md3dImmediateContext->OMSetBlendState(TransparentBS2, blendFactor, 0xffffffff);
		activeTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
		md3dImmediateContext->DrawIndexed(mBoxIndexCount, mBoxIndexOffset, mBoxVertexOffset);

here is my blend code


D3D11_BLEND_DESC transparentDesc = { 0 };
	transparentDesc.AlphaToCoverageEnable = false;
	transparentDesc.IndependentBlendEnable = false;

	transparentDesc.RenderTarget[0].BlendEnable = false;
	transparentDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
	transparentDesc.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
	transparentDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_SUBTRACT;
	transparentDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
	transparentDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
	transparentDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
	transparentDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
	HR(md3dDevice->CreateBlendState(&transparentDesc, &TransparentBS));


	


	transparentDesc.RenderTarget[1].BlendEnable = true;
	transparentDesc.RenderTarget[1].SrcBlend = D3D11_BLEND_ONE;
	transparentDesc.RenderTarget[1].DestBlend = D3D11_BLEND_ONE;
	transparentDesc.RenderTarget[1].BlendOp = D3D11_BLEND_OP_SUBTRACT;
	transparentDesc.RenderTarget[1].SrcBlendAlpha = D3D11_BLEND_ONE;
	transparentDesc.RenderTarget[1].DestBlendAlpha = D3D11_BLEND_ZERO;
	transparentDesc.RenderTarget[1].BlendOpAlpha = D3D11_BLEND_OP_ADD;
	transparentDesc.RenderTarget[1].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
	HR(md3dDevice->CreateBlendState(&transparentDesc, &TransparentBS2));

You have to create separate Blend states, not use the RenderTarget[] array in the blend desc. Also your blend desc is wrong for the second pass. See my last post. Your have to render the vines with BlendOp=BLEND_OP_REV_SUBTRACT (which is different from BLEND_OP_SUBTRACT), or render the vines first, then the bricks with BLEND_OP_SUBTRACT.

This topic is closed to new replies.

Advertisement