Rendering blended stuff before skybox?

Started by
3 comments, last by cozzie 9 years, 8 months ago

Hi,

I played around with the order af drawing stuff and setting states in my engine.

There are 3 main to be rendered things:

1 - opaque objects

2 - blended objects

3 - skybox

Preferably I want to render things in that order, but when I do this, the blended objects disappear/ are not visible.

If I switch 3 and 2, skybox first, then blended objects, it looks all fine.

Does someone have an idea why this happens/ which state I'm overlooking?

Or maybe the order 1, 3 is 2 is better anyway? (and why?)

Here's the code, working:


	/** OPAQUE: RENDER SCENE USING BASE UBERSHADER **/
	mStateMachine.SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
	mStateMachine.SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
	mStateMachine.SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
	mStateMachine.SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);

	if(!RenderScene(*pD3dscene, "SingleTexTech", mRenderQueue.GetRefRenderablesOpaque(), mRenderQueue.GetRefBucketOpaque())) return false;
	
	/** RENDER SKYBOX **/ 
	if(pD3dscene->HasSkybox())
	{
		if(!pD3dscene->mSkyBox.Render(pCam->GetPosition(), *pCam)) return false;
		mStateMachine.SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
		mStateMachine.SetRenderState(D3DRS_ZWRITEENABLE, FALSE);										
		mStateMachine.SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
		mStateMachine.SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
		mStateMachine.SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR);
	}

	/** BLENDED: RENDER SCENE USING UBERSHADER **/
	mStateMachine.SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
	mStateMachine.SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
	mStateMachine.SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);

	if(!RenderScene(*pD3dscene, "SingleTexTech", mRenderQueue.GetRefRenderablesBlended(), mRenderQueue.GetRefBucketBlendedSorted())) return false;

And not working (blended objects first):


	/** OPAQUE: RENDER SCENE USING BASE UBERSHADER **/
	mStateMachine.SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
	mStateMachine.SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
	mStateMachine.SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
	mStateMachine.SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);

	if(!RenderScene(*pD3dscene, "SingleTexTech", mRenderQueue.GetRefRenderablesOpaque(), mRenderQueue.GetRefBucketOpaque())) return false;

	/** BLENDED: RENDER SCENE USING UBERSHADER **/
	mStateMachine.SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
	mStateMachine.SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
	mStateMachine.SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);

	if(!RenderScene(*pD3dscene, "SingleTexTech", mRenderQueue.GetRefRenderablesBlended(), mRenderQueue.GetRefBucketBlendedSorted())) return false;

	/** RENDER SKYBOX **/ 
	if(pD3dscene->HasSkybox())
	{
		if(!pD3dscene->mSkyBox.Render(pCam->GetPosition(), *pCam)) return false;
		mStateMachine.SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
		mStateMachine.SetRenderState(D3DRS_ZWRITEENABLE, FALSE);										
		mStateMachine.SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
		mStateMachine.SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
		mStateMachine.SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR);
	}

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Advertisement

I would draw the skybox first since it should always be furthest in the background anyway and you should sort your opaque objects from back-to-front.

If you draw the skybox last, your transparent objects will only blend with opaque and other, previously drawn transparent ones, but not the skybox. This means they will get an edge around the transparent parts of the colour it was blended with which will be the render target clear colour in areas where only the skybox would be behind these objects. Of course this won't look pretty once the sky gets filled in to the non-transparent pixels surrounding those blended areas ;)

Actually with the code above, the blended objects are not visible at all.

I only get them visible in that rendering order, when I set D3DRS_ZWRITEENABLE to TRUE (instead of false). But then blending get's messed up.

Playing around so far didn't bring me the effect you're describing.

For now, I'll stick to opaque, skybox, transparent, since that gives the expected result (still don't understand though why I can't get the blended objects visible when rendering the skybox last). Switching skybox to 1 and then opaque works, but gives no difference (because I disable Z-write Always when drawing the skybox, and in the skybox shader is set pos.Z to pos.W so it's Always 1.

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Opaque geometry should be drawed from front to back and before any transparent objects. Sky box is opaque object so it has to be drawed before blended stuff.

Thanks, easy as it sounds, that makes a lot of sense.
Case closed :)

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

This topic is closed to new replies.

Advertisement