Blending two images together.

Started by
24 comments, last by terryeverlast 9 years, 1 month ago

Ok..my 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));


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

	

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

still the image

1073laq.jpg

Advertisement

What happens if you render the bricks only? Make sure to render the Bricks in the first pass and the vines afterwards. Try inverting the grayscale vines texture.

Also, calling Apply() after the first DrawIndexed call looks not correct.

Ok. I rendered the first image with no blend state. The wooden crate is the first image.

The second image I converted to RGBA and put a blend on it.

This is what im getting

28hlaau.jpg

My code is


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

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

		Effects::BasicFX->SetWorld(world);
		Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose);
		Effects::BasicFX->SetWorldViewProj(worldViewProj);
		Effects::BasicFX->SetTexTransform(XMLoadFloat4x4(&mTexTransform));
		Effects::BasicFX->SetMaterial(mBoxMat);
		Effects::BasicFX->SetDiffuseMap(mDiffuseMapSRV);
		md3dImmediateContext->RSSetState(NoCullRS);
		activeTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
		md3dImmediateContext->DrawIndexed(mBoxIndexCount, mBoxIndexOffset, mBoxVertexOffset);
		Effects::BasicFX->SetDiffuseMap(mDiffuseMapSRV2);
		md3dImmediateContext->OMSetBlendState(mb2, blendFactor, 0xffffffff);
		activeTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
		md3dImmediateContext->DrawIndexed(mBoxIndexCount, mBoxIndexOffset, mBoxVertexOffset);



    }

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

and my blend code


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

	myblend2.RenderTarget[0].BlendEnable = true;
	myblend2.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
	myblend2.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
	myblend2.RenderTarget[0].BlendOp = D3D11_BLEND_OP_REV_SUBTRACT;
	myblend2.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
	myblend2.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
	myblend2.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
	myblend2.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
	HR(md3dDevice->CreateBlendState(&myblend2, &mb2));

Why is it blue and not the subtracting the two images??

Am I leaving out something?

md3dImmediateContext->OMSetBlendState(mb2, blendFactor, 0xffffffff);

Is making it blue.

I don't see you setting the opaque (no-blend) blendstate. In the second frame you render your first pass with the blend shader then, which is obviously not what you want ;)

The object is blue then, because it blends with the clear color, which is blue.

Also, what ist your blendFactor?

My blendFactor is {0.0f, 0.0f, 0.0f, 1.0f};

I did the opaque state with it now. Not blue anymore, just the normal first image crate withouth the second image.

How would you set the code up in the code below?


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

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

		Effects::BasicFX->SetWorld(world);
		Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose);
		Effects::BasicFX->SetWorldViewProj(worldViewProj);
		Effects::BasicFX->SetTexTransform(XMLoadFloat4x4(&mTexTransform));
		Effects::BasicFX->SetMaterial(mBoxMat);
		Effects::BasicFX->SetDiffuseMap(mDiffuseMapSRV);
		md3dImmediateContext->RSSetState(NoCullRS);
		activeTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
		md3dImmediateContext->DrawIndexed(mBoxIndexCount, mBoxIndexOffset, mBoxVertexOffset);
		Effects::BasicFX->SetDiffuseMap(mDiffuseMapSRV2);
		md3dImmediateContext->OMSetBlendState(mb2, blendFactor, 0xffffffff);
		activeTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
		md3dImmediateContext->DrawIndexed(mBoxIndexCount, mBoxIndexOffset, mBoxVertexOffset);



    }

Assuming you have a blendstate mb with BlendEnable=FALSE:


activeTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
Effects::BasicFX->SetDiffuseMap(mDiffuseMapSRV);
md3dImmediateContext->OMSetBlendState(mb, blendFactor, 0xffffffff); // <<========
md3dImmediateContext->DrawIndexed(mBoxIndexCount, mBoxIndexOffset, mBoxVertexOffset);
Effects::BasicFX->SetDiffuseMap(mDiffuseMapSRV2);
md3dImmediateContext->OMSetBlendState(mb2, blendFactor, 0xffffffff);
//activeTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);    not required
md3dImmediateContext->DrawIndexed(mBoxIndexCount, mBoxIndexOffset, mBoxVertexOffset); 

If you only see the brick texture with this, your second texture (mDiffuseMapSRV2) might be wrong. Either it doesn't get loaded properly or all RGB channels are empty. If you like, you may attach your second texture.

If you use a Visual Studio with Graphics Diagnostics Tools, you may also capture a frame and attach the vsglog.

Ok. Ive been on blending two images together for awhile now and not getting any luck.

Will someone go to http://www.d3dcoder.net/d3d11.htm, download the SOURCE CODE SET I, and in "Chapter 9 Blending" is a blend project.

Make the water blend with another image. Blend the water with a grayscale image or any image you can using the OMSetBlendState

I need help on this. thank you

At this point in the discussion, it's not clear exactly how you're rendering the object(s). So, just a guess, you can't get your blending to work properly because you're drawing the same object twice. The second time you draw, nothing is drawn because the object is rejected due to the depth test.

To alpha blend two textures when drawing the same object twice:

1. Draw the object "normally" with the opaque texture - blending disabled.

2. Enable alpha blending as Ashaman73 provides above.

3. Set the depth stencil state DepthFunc to D3D11_COMPARISON_LESS_EQUAL.

4. Draw the object with the alpha texture - blending enabled, and depth testing set to LESS_EQUAL

EDIT: what that change in the depth func does is to NOT reject the second pixel drawn even though the depth is the same as the pixel at the same location.

You may want to set the depth stencil state func back to LESS after the second draw.

Just a test case I put together. Below is a box drawn first with a brick texture. Then alpha blending is enabled, depth state func is set to LESS_EQUAL, the box is drawn a second time with a png texture that's just a white texture with alpha set to 0 outside a circular area. FYI, the box is actually centered at the origin, so the lower half is "covered" by the reference ground grid.

[attachment=26336:captured11.png]

EDIT2: In general, I wouldn't rely on that method to blend textures on a surface. I'm not sure that, in some cases, you wouldn't get z-fighting. Stenciling might work better (as that appears to be what you're actually doing). Another approach might be to just combine the textures in a single pass in the pixel shader, doing your own alpha calcs to combine the colors.

EDIT3: If, for whatever reason, water1.dds is important to you -

[attachment=26337:captured11.png]

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

You talked about blending images in the way, that the second image color is subtracted from the previous one. On that site, what is done is alpha blending. These are different things.
Sorry, but what exactly is your goal?

Pixel rejection might well be an issue, but what is strange here, is that in his post of 05 March 2015 - 03:15 Pm, I do see the vines (the second texture). This let's me assume that all of the second geometry pixels are drawn.

This topic is closed to new replies.

Advertisement