Sign in to follow this  

(solved) Probably stupid question on unsigned int / effect->begin

This topic is 1838 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

Can't figure it out, probably something stupid...
I have:

unsigned int *numpasses = new unsigned int[2];		// CLEAN UP!!!	numpasses[0] = 1;									// CLEAN UP!!!	mSkyBoxEffect->Begin(&numpasses[0], D3DXFX_DONOTSAVESTATE);

But in this situation (function within class) I always have only 0 pass for the shader.

Is there a way to pass '1' to the D3DXEFFECT->Begin function without creating the array?

Feels like a waste to create the array of unsigned ints..

Share this post


Link to post
Share on other sites

I'm not a DirectX user, but it seems to me from the documentation that it only wants a pointer to an unsigned int so it can return the number of passes needed to do the operation. Surely something like this would work?

 

[code]unsigned int numpasses=1; mSkyBoxEffect->Begin(&numpasses, D3DXFX_DONOTSAVESTATE);[/code]

Share this post


Link to post
Share on other sites
In general you write it like this:
UINT numPasses = 0;
mFX->Begin(&numPasses, 0);
....

Like FLEBlanc said, DirectX will fill the variable you are passing in, with the amount of passes. Edited by Paxi

Share this post


Link to post
Share on other sites

Great, thanks for the quick reactions.

Both solutions will work, will get into it.

 

Not sure if BeginPass will do, because then I can't use the flag (D3DXFX_DONOTSAVESTATE);

Share this post


Link to post
Share on other sites
You need to do a begin on the effect first anyway, after that you only want to render pass one of the technique you specify, right? In any case after begin on the effect you need to do a BeginPass anyway to render with a pass in that active technique, read the remarks on both documentation pages.

Generally rendering with D3DXEffect looks like this
unsigned int numberOfPassInActiveEffect = 0;
m_effect->Begin(&numberOfPassInActiveEffect); //This sets the variable to the number of passes this technique has
for (unsigned int counter = 0; counter < numberOfPassInActiveEffect; ++counter)
{
    m_effect->BeginPass(counter);
    //Do pass specific passing of uniforms here
    m_effect->CommitChanges();
    //Do render calls here
    m_effect->EndPass();
}
m_effect->End();

If you only want to render one pass in the current effect instead of looping on all available passes, just activate the pass you are interested in with ID3DXEffect::BeginPass(unsigned int passNumber), and do your rendering.

Share this post


Link to post
Share on other sites

Thanks, that looks clear.

What I don't understand is why your 'Begin' function has only one parameter, I can use a 2nd using flags, like D3DXFX_DONOTSAVESTATE.

 

What do you mean with pass specific passing of uniforms? (is this setting the vars in the shader)

Like to take this opportunity to improve my frame rendering using shaders.

 

I know do the following each frame (pseudo code):

 

// rendering the meshes

- loop through all effects/shaders

- setup vars for effect: SetTechnique, SetMatrix(viewproj)

- effect->Begin

- loop through all materials

- select the material: SetFloatArrays for effect (MatAmb, MatDiff)

- loop through all meshes

- set the streamsource (vertex and indexbuffer)

- and then:

 

for(unsigned int i=0;i<pD3dscene->mEffectNumPasses[ec];++i)

{

pD3dscene->mEffect[ec]->BeginPass(i);

pD3dscene->mD3dMeshes[oc].RenderAttr(mD3ddev, att, LIST);

++mAttrRendered;

pD3dscene->mEffect[ec]->EndPass();

}

 

Is there anything wrong in this order/ should I set the effect vars after the 'BeginPass'? (functionally it all works)

 

Here the 'cleaned up' code of my renderframe function:

 

 bool CD3d::RenderFrameV2(CD3dscene *pD3dscene, CD3dcam *pCam)
{
	if(!CheckDevice()) { mDeviceLost = true; return true; }
	mObjRendered = 0;	mAttrRendered = 0;
	
	pCam->Update();

	mD3ddev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
	mD3ddev->BeginScene();

	// WORLD MESHES; SHADER RENDERING
	for(ec=0;ec<pD3dscene->mNrEffects;++ec)
	{
		if(!SetVertexShader(pD3dscene, ec, "BasicShader", pCam)) return false; // Sets Technique and Vieproj matrix
		pD3dscene->mEffect[ec]->Begin(&pD3dscene->mEffectNumPasses[ec], D3DXFX_DONOTSAVESTATE);

		for(mc=0;mc<pD3dscene->mNrMaterials;++mc)
		{
			if(!pD3dscene->PreSelectMaterial(mc, ec)) return false;		// Sets 'MatAmb' and 'MatDiff' in the current 'effect/shader'

			for(oc=0;oc<pD3dscene->mNrD3dMeshes;++oc)
			{
				if(pD3dscene->mD3dMeshes[oc].mEffectIndex == ec) 
				{
					if(pCam->SphereInFrustum(&pD3dscene->mD3dMeshes[oc].mWorldPos,
						pD3dscene->mD3dMeshes[oc].mBoundingRadius))
					{
						if(!pD3dscene->PreSelectMesh(oc, mD3ddev)) return false; // Sets the streamsource, vtx/ index buffers
						for(DWORD att=0;att<pD3dscene->mD3dMeshes[oc].mAttrSize;++att)
						{
							if(pD3dscene->mD3dMeshes[oc].mMatIdPerAttr[att] == mc)
							{
								if(pCam->SphereInFrustum(&pD3dscene->mD3dMeshes[oc].mAttrWorldPos[att], 
									                     pD3dscene->mD3dMeshes[oc].mAttrBoundingRadius[att]))
								{						
									for(unsigned int i=0;i<pD3dscene->mEffectNumPasses[ec];++i)
									{
										pD3dscene->mEffect[ec]->BeginPass(i);
										pD3dscene->mD3dMeshes[oc].RenderAttr(mD3ddev, att, LIST);
										pD3dscene->mEffect[ec]->EndPass();
									}
								}
							}
						}
					}
				}
			}
		}
		pD3dscene->mEffect[ec]->End();
	}

	// SKY BOX; SHADER RENDERING
	if(pD3dscene->mSkyBoxInScene) 
		if(!pD3dscene->mSkyBox.Render(pCam->mPosition, pCam, mD3ddev)) return false;

	// FFP rendering
	if(!SetDefaultRenderStates()) return false;
	mD3ddev->EndScene();
	HRESULT hr = mD3ddev->Present(NULL, NULL, NULL, NULL); 

	return true;
}

Share this post


Link to post
Share on other sites

@nightcreature; I looked it up in MSDN and found the following on CommitChanges():

 

If the application changes any effect state using any of the ID3DXEffect::Setx methods inside of an ID3DXEffect::BeginPass/ID3DXEffect::EndPass matching pair, the application must call ID3DXEffect::CommitChanges before any DrawxPrimitive call to propagate state changes to the device before rendering. If no state changes occur within a ID3DXEffect::BeginPass and ID3DXEffect::EndPass matching pair, it is not necessary to call ID3DXEffect::CommitChanges.

 

This means I don't have toe use it 'today'.

I now do one of two things:

 

1. on initialization setup renderstates

2. ech frame frame render order: A. meshes through shader, states only in shader, no setrenderstates while shade rendering

3. render skybox using shader, setrenderstates, draw using effect, setrenderstates back (cull/ zwrite)

4. draw text using FFP

 

And optional reset RenderStates after step 3, when I use: effect->Begin(numpasses, D3DXFX_DONOTSAVESTATE).

 

In the future it might be usefull to use CommitChanges(), because I need to combine sets of objects within one pass/ effect (now probably unneccessary passes/ loops).

 

This does clear things up, few weeks ago I was trying to combine things within one begin/end of an effect, and ran into the problem that I couldn't change matrices etc, and therefor got back to multiple loops with an effect. Now I know how to do this :) Thanks

Share this post


Link to post
Share on other sites
Sign in to follow this