DX10 Effect Question

Started by
4 comments, last by bushmanpaul 13 years, 6 months ago
Hi all,

I am new to DirectX 10 and I am having trouble understanding how the effects work. Naturally I have a few questions I was hoping someone could answer for me.

I am trying to write some code for my engine so that I can attach a number of effects to an object. For example I currently have 2 .fx files one which applies a texture and the other simply colors the object red.

My first question is how do the techniques work? Is it possible to render an object using more than one technique? It seems that the next technique just overwrites what the previous one rendered. None of the examples demonstrate what I am trying to achieve, is it even possible?

Secondly I am having an issue with the inputs into my second pixel shader when I apply the effect that turns the object red then the effect which renders a texture.

I get the following error.

D3D10: ERROR: ID3D10Device::DrawIndexed: Input Assembler - Vertex Shader linkage error: Signatures between stages are incompatible. The reason is that the input stage requires Semantic/Index (TEXCOORD,0) as input, but it is not provided by the output stage. [ EXECUTION ERROR #342: DEVICE_SHADER_LINKAGE_SEMANTICNAME_NOT_FOUND ]

I don't quite understand what the cause of this error is. Could someone explain that to me?

Cheers,
Advertisement
Bad news, you can't do what you want like this :) That means that the colouring and shading should be done in a single shading program (a single pass). Of course, there are other, deferred approaches... Somebody could talk a little about those.

Basically the whole Pass and Technique thing is just some encapsulation of shading programs. Each .fx file can contain several Techniques, each of which can have several Passes. Think of it as a library of shading programms.

At runtime, you can then select a specific Pass and render using that. What happens when you render again using (perhaps) another Pass of perhaps another Technique depends on blending states (for example) but that is NOT (much) different from DX9 or OpenGL or anything.

The problem with the IA-VS linkage error can be solved by setting correct (data) layout for the input assembler (that's a part of the graphics pipeline before the VS). You need to tell IA how your primitive data looks like. Look up D3D10_INPUT_ELEMENT_DESC and ID3D10Device::CreateInputLayout.
Thanks mate, that does shed some more light on the situation.

As for the error. Sorry I should have posted more information. I have set up the input assembler properly, but what I think is happening is that the state isn't getting cleared out after I have applied each effect. I know this because if I only apply one of the effects, the one I have applied seems to work.

Is there a way to flush out the Input Assembler stuff during a draw call? Is it too expensive to do this.

Here are some code snippets of what I am trying to do.

void CDx10Renderer::ApplyEffects(){	if( m_pCurrentVisualObject->GetNumEffects() <= 0 )	{		ApplyCoreEffect();	}	else	{		for( unsigned int i = 0; i < m_pCurrentVisualObject->GetNumEffects(); ++i )		{			m_pActiveEffect = reinterpret_cast< CDx10Effect* >( m_pCurrentVisualObject->GetEffect(i) );			//obtain the variables			m_pWorldVariable = m_pActiveEffect->GetVariableByName( "World" )->AsMatrix();			m_pViewVariable	 = m_pActiveEffect->GetVariableByName( "View" )->AsMatrix();			m_pProjVariable	 = m_pActiveEffect->GetVariableByName( "Projection" )->AsMatrix();			//update variables			m_pWorldVariable->SetMatrix( ( float* )&m_World.ToTranspose() );			m_pViewVariable ->SetMatrix( ( float* )&m_pActiveCamera->GetViewMatrix() );			m_pProjVariable ->SetMatrix( ( float* )&m_pActiveCamera->GetProjectionMatrix() );			m_pActiveEffect->Apply();			for( unsigned int j = 0; j < m_pActiveEffect->GetNumTechniques(); ++j )			{				m_pActiveTechnique = m_pActiveEffect->GetTechiqueByIndex( 0 );				//Set VertexFormat				SetVertexFormat( *m_pCurrentVisualObject->GetVertexFormat() );				//enable Buffers				EnableResourceBuffer( m_pCurrentVisualObject->GetIndexBuffer() );				EnableResourceBuffer( m_pCurrentVisualObject->GetVertexBuffer() );				//set topology				m_pD3d10Device->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST );				//Draw				D3D10_TECHNIQUE_DESC techDesc;				m_pActiveTechnique->GetDesc( &techDesc );				for( unsigned int k = 0; k < techDesc.Passes; ++k )				{					m_pActiveTechnique->GetPassByIndex( k )->Apply( 0 );					m_pD3d10Device->DrawIndexed( reinterpret_cast<CIndexBuffer*>(m_pCurrentVisualObject->GetIndexBuffer())->GetNumIndices(), 0, 0 );				}			}		}	}}


Here is the enable resource buffer function
	D3D10_BUFFER_DESC desc;	tBufferDesc otherDesc = _pBuffer->GetDesc();	desc.BindFlags		= otherDesc.m_uiBindFlags;	desc.ByteWidth		= otherDesc.m_uiBufferSize;	desc.CPUAccessFlags = otherDesc.m_uiCPUAcessFlags;	desc.MiscFlags		= otherDesc.m_uiMiscResourceFlags;	desc.Usage			= (D3D10_USAGE)otherDesc.m_uiUsage;	D3D10_SUBRESOURCE_DATA subResourceData;	CSystem::Memcpy( &subResourceData, sizeof( D3D10_SUBRESOURCE_DATA ), &_pBuffer->GetBufferData(), sizeof( D3D10_SUBRESOURCE_DATA ) );	switch( _pBuffer->GetType() )	{		case BUFFER_BIND_INDEX_BUFFER:		{			if( !m_pIndexBuffer )			{				s_hResult = m_pD3d10Device->CreateBuffer( &desc, &subResourceData, &m_pIndexBuffer ); 				assert( SUCCEEDED( s_hResult ) );			}			m_pD3d10Device->IASetIndexBuffer( m_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 );		}		break;		case BUFFER_BIND_VERTEX_BUFFER:		{			if( !m_pVertexBuffer )			{				s_hResult = m_pD3d10Device->CreateBuffer( &desc, &subResourceData, &m_pVertexBuffer ); 				assert( SUCCEEDED( s_hResult ) );			}			unsigned int uiStride = reinterpret_cast<CVertexBuffer*>( _pBuffer )->GetVertexSize();			unsigned int uiOffset = 0;			m_pD3d10Device->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &uiStride, &uiOffset ); 		}		break;	}
Instead of separate techniques try a single technique with separate passes or even better use a single pass.
I have been considering the following approach.

Creating a number of techniques based on versions of pixel and vertex shaders available. For example.

technique10 Render_1_0{    //do version 1.0 stuff only}technique10 Render_2_0{    //do more sophisticated version 2.0 stuff as well}


I have seen examples where people have created functions inside .fx files to do specific tasks but not necessarily include techniques or passes in those files. For example a file called Texture.fx might have a pixel shader and vertex shader function for applying a texture to a mesh.

Ultimately my goal is to be able to combine different shaders easily so I could separate out different shaders into files and name them accordingly to what they do.

But I am still a little confused as to how to pull in shaders from other files and get them to work.

consider the following example

technique10{    pass p0    {        SetPixelShader( CompileShader( ps_4_0, ShaderThatTurnsItRed() ) );        SetPixelShader( CompileShader( ps_4_0, ShaderThatTurnsItBlue() ) );    }}


Is it possible have the resulting object be coloured purple instead of being coloured red then being overwritten with a blue colour?

Obviously one could write a single shader that did that, but I am trying to reuse existing shaders to create a new effect by combining them instead of rewriting another shader with both functions combined.

Cheers
Yes you could if you blend the two outputs together.

You just have to set the blend state so that blending is possible.

http://takinginitiative.net/2010/04/09/directx-10-tutorial-6-transparency-and-alpha-blending/ explains and shows you how to do the blending.

Hope this helps.

This topic is closed to new replies.

Advertisement