Sign in to follow this  
Claudio

pass variable

Recommended Posts

Hi. My code use DirectX and is composed by c++ file and fx file. In other words, I use the Gpu of Nvidia graphic card. In other words, I've to take a variable in a c++ file and transfer its value in the Fx file.
 

//---HEADER
//    Name:    Default
//    Desc:    Per-Pixel basic diffuse lighting with one white directional-light
//------------------------------------------------------------------>
string effectName = "Orange Effect";
string effectDescription = "a Default Material";

//---INCLUDE
//------------------->
#include "Utility.fxh"

//---CONNECTORS
//-------------->
struct Vertex
{
//    Everything is in Model Coord
    float3 position     : POSITION;
    float3 normal        : NORMAL;
};
struct FragmentA
{
    float4 position    : POSITION;
    float3 normal_VC    : TEXCOORD0;
};
struct FragmentB
{
    float4 position    : POSITION;
    float4 color    : COLOR0;
};
struct Pixel
{
    float4 color        : COLOR;
};

//---PARAMETERS
//------------------------------>
row_major float4x4 world : WORLD;
row_major float4x4 view : VIEW;
row_major float4x4 proj : PROJECTION;

// // // diffuse light:
float4 baseColor : DIFFUSECOLOR = float4(0.8f,0.8f,0.8f,0.7f);
const float DiffuseIntensity = 1;
// // // direction light:
float3 VectorLightDirection = - normalize(float3(0, 0.6, -0.8));
float3 NormVectorLightDirection;

//---SHADERS
//------------------------------------------------------->
void PerPixelVS(    in Vertex vertex, out FragmentA fragment,
                        uniform float4x4 world,uniform float4x4 view,uniform float4x4 proj)
{
//    Compute WORLDVIEWPROJECTION matrix (preshader)    
    float4x4 worldViewProj = mul(world,mul(view,proj));
    float4x4 worldView = mul(world,view);
    
//    Compute Screen Space Position    
    fragment.position = mul(float4(vertex.position,1),worldViewProj);

//    Pass view coordinate normal to pixel shader for lighting [vertex.normal * Transpose(Inverse(worldView));
    fragment.normal_VC = mul(float4(vertex.normal,0),worldView);
    
     NormVectorLightDirection = -normalize(mul(float4(VectorLightDirection, 0), worldView));
}
void PerPixelPS(in FragmentA fragment,out Pixel pixel)
{
   // directional light:
   pixel.color.xyz = baseColor.xyz * saturate(DiffuseIntensity * dot(normalize(fragment.normal_VC), NormVectorLightDirection));    
     //ps_1_1: error! texcoord are restricted to [0,1]
   pixel.color.w = baseColor.w;
}

void PerVertexVS(    in Vertex vertex,out FragmentB fragment,
                        uniform float4x4 world,uniform float4x4 view,uniform float4x4 proj)
{
//    Compute WORLDVIEWPROJECTION matrix (preshader)    
    float4x4 worldViewProj = mul(world,mul(view,proj));
    float4x4 worldView = mul(world,view);
    
//    Compute Screen Space Position    
    fragment.position = mul(float4(vertex.position,1),worldViewProj);

//    Compute color
    NormVectorLightDirection = -normalize(mul(float4(VectorLightDirection, 0), worldView));

  // directional light:
  fragment.color.xyz = baseColor.xyz * saturate(DiffuseIntensity * dot(normalize(mul(float4(vertex.normal,0),worldView)), NormVectorLightDirection));
  fragment.color.w = baseColor.w;
}
void PerVertexPS(in FragmentB fragment,out Pixel pixel)
{
    pixel.color = fragment.color;
}


The user move a external point on the surface of the 3d object and I want to pass the postition of this external point to the fx file. I think use uniform-qualify because is costant in the istants of time in which the user don't move the esternal object. If I create a variable with the same name in the fx file and define the variable "extern" in the c++ file and if I define the variable like "uniform", the result is that the value is always zero. And so I don't know how solve the problem. Someone know how I can solve this problem ? Thanks.

Share this post


Link to post
Share on other sites
Your shaders are NOT part of your C++ program. They are compiled seperately in a seperate language. You must use the effect API to change the values of the variables when the effect is used.

Read:
http://msdn.microsoft.com/en-us/library/bb205076(VS.85).aspx

Especially read about setting resources and states.

Share this post


Link to post
Share on other sites
Quote:
Original post by brekehan
Your shaders are NOT part of your C++ program. They are compiled seperately in a seperate language.


Yes I know that the Fx file is not in C++ but in other language.

Share this post


Link to post
Share on other sites
You need to setup an effect in DirectX, here is an example... don't think it needs anymore explanation, just look at the source.

2nd sample down
http://www.codesampler.com/dx9src/dx9src_8.htm

The IDirect3DEffect interface provides functions for setting custom parameters in a shader. i.e SetFloat, SetValue(for custom i.e vectors), SetMatrix etc, surly you are calling SetMatrix already?


//Shader code
uniform extern float3 myVector;
uniform extern float myFloat;

//C++ code
D3DXVECTOR3 vec(a,b,c);
float f = 10.0f;
IDirect3DEffect9 * effect = getEffect("MyEffect");
effect->SetValue("myVector", &vec, sizeof(D3DXVECTOR3));
effect->SetFloat("myFloat", &f);



Also bear in mind that if a value in a shader has no effect/bearing on the output, then it is compiled out, so if you are passing in values fine but not using them, they will be compiled out of the shader... which might explain why they show up as 0 or null in pix. You can avoid this by adding the D3DXSHADER_SKIPOPTIMIZATION flag when you compile your effect. Set your DX CP to enable shader debuging too.

Good luck.

Share this post


Link to post
Share on other sites
Quote:
Original post by reaper93
The IDirect3DEffect interface provides functions for setting custom parameters in a shader. i.e SetFloat, SetValue(for custom i.e vectors), SetMatrix etc, surly you are calling SetMatrix already?
 
//Shader code
uniform extern float3 myVector;
uniform extern float myFloat;

//C++ code
D3DXVECTOR3 vec(a,b,c);
float f = 10.0f;
IDirect3DEffect9 * effect = getEffect("MyEffect");
effect->SetValue("myVector", &vec, sizeof(D3DXVECTOR3));
effect->SetFloat("myFloat", &f);



Visual CPlusPlus return an error about the function "getEffect": identifier not found also with a search depending by the argument.

I'm also looking the code example that you suggest me.

Did you refer with "getEffect" to use the function "D3DXCreateEffectFromFile" ? This because there isn't any function that "get" the effect from the Fx file but there are only function that "create" effect from file.

Thanks.

[Edited by - Claudio on January 22, 2009 9:10:24 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by reaper93

2nd sample down
http://www.codesampler.com/dx9src/dx9src_8.htm

iDirect3DEffect interface - i.e SetFloat, SetValue, SetMatrix etc,
*** Source Snippet Removed ***


My problem is, in other words, that I've to shared a variable between a C++ file and Fx file.

I think that I've to get the effect from the fx file and then update the value of the shared variable.

Is correct this solution ?

The new problem became how get the effect from the file, because I can only create the effect from the file looking in the help of C++.

I've try the follow solution but I don't notice any type of difference in the update of the shared variable: the follow code is in the c++ file:

	LPD3DXBUFFER pCode;
DWORD dwShaderFlags = 0;
LPD3DXBUFFER pBufferErrors = NULL;
D3DXCompileShaderFromFile( "ORANGE.FX", NULL, NULL, "PerVertexVS", "vs_1_1", dwShaderFlags, &pCode, &pBufferErrors, &g_pConstantTablePerVertexVS);

// Create the vertex shader
fxEngine.GetDevice()->CreateVertexShader( (DWORD*)pCode->GetBufferPointer(), &g_pVertexShader );
pCode->Release();

D3DXCompileShaderFromFile( "ORANGE.FX", NULL, NULL, "PerPixelPS", "ps_2_0", dwShaderFlags, &pCode, &pBufferErrors, &g_pConstantTablePerPixelPS);

// Create the vertex shader
fxEngine.GetDevice()->CreatePixelShader( (DWORD*)pCode->GetBufferPointer(), &g_pPixelShader );
pCode->Release();


and then I update the shared variable:

//	D3DXCompileShaderFromFile( "ORANGE.FX", NULL, NULL, " ", " ", dwShaderFlags, &pCode, &pBufferErrors, &g_pConstantTableVS);
// g_pConstantTablePerVertexVS->SetValue(fxEngine.GetDevice(), "VariabileInFileFx", &prova, sizeof(Vector3));
// g_pConstantTablePerPixelPS->SetValue(fxEngine.GetDevice(), "VariabileInFileFx", &prova, sizeof(Vector3));


where "VariabileInFileFx" is the shared variable.

Do you know another solution ?

Thanks.

Share this post


Link to post
Share on other sites
Quote:
Original post by reaper93
The IDirect3DEffect interface provides functions for setting custom parameters in a shader. i.e SetFloat, SetValue(for custom i.e vectors)....


At the moment I take the effect from file and then I try to modify the value of the variable for the Fx file:
1 - create pool with:
 D3DXCreateEffectPool(&ppPool); 



2 - create effect from file with:
 	HRESULT resultPVS = D3DXCreateEffectFromFile(fxEngine.GetDevice(), "DATA\\ORANGE.FX", NULL, NULL, dwShaderFlags, ppPool, &ppEffectPVS, ppCompilationErrors);
HRESULT resultPPS = D3DXCreateEffectFromFile(fxEngine.GetDevice(), "DATA\\ORANGE.FX", NULL, NULL, dwShaderFlags, ppPool, &ppEffectPPS, ppCompilationErrors);
HRESULT resultPVO = D3DXCreateEffectFromFile(fxEngine.GetDevice(), "DATA\\ORANGE.FX", NULL, NULL, dwShaderFlags, ppPool, &ppEffectPVO, ppCompilationErrors);



3 - get the technique from the Fx file with:
 m_pTechniquePerPixel = ppEffectPPS->GetTechniqueByName( "perPixel" );
m_pTechniquePerVertex = ppEffectPVS->GetTechniqueByName( "perVertex" );
m_pTechniquePerVertexOnly = ppEffectPVO->GetTechniqueByName( "vertexOnly" );



4 - get the handle of the variable in the Fx file with:
 handle_pos_probePVS = ppEffectPVS->GetParameterByName(NULL, "lastProbePosition_OC");    
handle_pos_probePPS = ppEffectPPS->GetParameterByName(NULL, "lastProbePosition_OC");
handle_pos_probePVO = ppEffectPVO->GetParameterByName(NULL, "lastProbePosition_OC");



5 - set the update value for the variable in the Fx file (from the C++ file) with:
 ppEffectPVS->SetValue(handle_pos_probePVS, &lastProbePosition_OC, sizeof(Point3)); // modify "value"
ppEffectPVS->CommitChanges(); // change state before render !!!
ppEffectPPS->SetValue(handle_pos_probePPS, &lastProbePosition_OC, sizeof(Point3)); // modify "value"
ppEffectPPS->CommitChanges(); // change state before render !!!
ppEffectPVO->SetValue(handle_pos_probePVO, &lastProbePosition_OC, sizeof(Point3)); // modify "value"
ppEffectPVO->CommitChanges(); // change state before render !!!




The result is that at the step 5, I show (in a messagebox) if the value is change or not and it appear that the value is set. But when appear the window with DirectX, don't appear in the window the color that I search and so I think that don't change the value.

Also if I set the technique (I've to use it ???) with "SetTechnique" from ID3DXEffect (after "GetParameterByName"), the result is the same described before.

Someone know where is my error ??? or know another solution ???

Thanks.

[Edited by - Claudio on January 26, 2009 4:15:33 AM]

Share this post


Link to post
Share on other sites
Quote:

Also if I set the technique (I've to use it ???) with "SetTechnique" from ID3DXEffect (after "GetParameterByName"), the result is the same described before.


You'll have to call the Begin() method on your effect object to start using it, draw your primitives and when you're done with it you'll have to call End() on the object. You'll also have to iterate over the passes in the technique or take the quick and dirty workaround and just call BeginPass() and EndPass() on the first (and typically only) pass.

Over here on MSDN you'll find a complete code-sample and some step-by-step instructions (check near the bottom for the Begin/End instructions). You might also want to check the main effects index page for more information.

Hope this helps :)

Share this post


Link to post
Share on other sites
Variables are NOT shared between C++ and the FX file. You have two separate variables, regardless of using extern and naming them the same thing.

You can use the ID3DXEffect API to set the variable in the FX file.

Also, data cannot flow the other way. The FX file cannot store values into the variable. The only mechanism to get data from the GPU back to the CPU is to have those values pass through the entire pipeline and written as colors to a render target.

Share this post


Link to post
Share on other sites
If I've (in a only one Fx file) three techinque that use the same variable that I wont to update, have I to create three effect with:

 D3DXCreateEffectFromFile 


or only one effect with three techinque inside ??? And in the last case (one effect with three techinque), when I use:

 SetTechnique 


I overwrite the technique when re-use "SetTechnique" or not ???

Thanks for all.

Share this post


Link to post
Share on other sites
You'll make 1 ID3DXEffect object that has all 3 techniques in it.

SetTechnique is used to choose which technique the next draw will use. You can call this as often as you like, to draw different objects with different techniques (ie: one technique for skinned meshes, and another technique for a regular mesh). If these techniques use the same variables, the ID3DXEffect system will make sure the variable contains the last set value, even if it was set when using a different technique.

Share this post


Link to post
Share on other sites
Quote:
Original post by Namethatnobodyelsetook
You'll make 1 ID3DXEffect object that has all 3 techniques in it.

SetTechnique is used to choose which technique the next draw will use. If these techniques use the same variables, the ID3DXEffect system will make sure the variable contains the last set value, even if it was set when using a different technique.


So, I create only one effect from file and then a set the first technique ("SetTechnique" for the first time), then modify the value; then, I can set the second technique with "SetTechnique" and modify the value for this second technique; then, I can set the third technique with "SetTechnique" and modify the value for this third technique.

And the ID3DXEffect system (and not I ???) will make sure the variable contains the last set value, even if it was set when using a different technique.

Share this post


Link to post
Share on other sites
Quote:
Original post by Namethatnobodyelsetook
You'll make 1 ID3DXEffect object that has all 3 techniques in it.


But i can create also three effect, every one with only one technique, is right ??? or not ??? So, I could modify the value for the three technique only in one point consecutively.

Thanks for all.

Share this post


Link to post
Share on other sites
If you have 1 FX file, with 3 techniques that share a variable, and you do:

SetTechnique(A)
SetFloat(sharedVarHandle, 1.0f);
SetTechnique(B)
SetFloat(sharedVarHandle, 2.0f);
SetTechnique(C)
SetFloat(sharedVarHandle, 3.0f);

then the shared variable will have the value of 3.0f in all 3 techniques...

You can make 3 seperate effect objects, though the overhead of changing shaders is far larger than the overhead of changing a variable and using the same shader.

Share this post


Link to post
Share on other sites
Quote:
Original post by Namethatnobodyelsetook
If you have 1 FX file, with 3 techniques that share a variable, and you do:

SetTechnique(A)
SetFloat(sharedVarHandle, 1.0f);
SetTechnique(B)
SetFloat(sharedVarHandle, 2.0f);
SetTechnique(C)
SetFloat(sharedVarHandle, 3.0f);

then the shared variable will have the value of 3.0f in all 3 techniques...


If I use only one effect with three technique, as in the code you have written, I set the share variable for the techinque A to 1.0f, B to 2.0f and C to 3.0f and not A, B and C to 3.0f ???

Yes, I understand:

Quote:
Original post by Namethatnobodyelsetook
You can make 3 seperate effect objects, though the overhead of changing shaders is far larger than the overhead of changing a variable and using the same shader.


I don't know if in this reasoning, I make an error.

Other question:
the use of CommitChanges, Begin, BeginPass, EndPass, End:
I have to use them when I render the 3D scene ??? and the use of "setvalue" (of ID3DXEffect) is between Begin and BeginPass ??? and CommitChanges is between BeginPass and EndPass. In other words is correct the follow order of function ???



1 - CreateEffectFromFile in the initializzation of the application
1.1 - effect->GetTechnique(...)
1.2 - GetParameter ByName(...)
1.3 - m_technique=effect->SetTechnique(...)

2 - in the phase of rendering the 3D scene:
2.1 - effect->Begin(NULL, 0)
2.2 - effect->SetValue(shareVariable, valoreVector)
2.3 - effect->BeginPass(0) // I have "pass single" in each technique
2.4 - effect->CommitChanges()
2.5 - effect->EndPass()
2.6 - effect->End()
2.7 - rendering of the 3D scene






Is correct the order ???

Thanks.

[Edited by - Claudio on January 27, 2009 3:54:34 AM]

Share this post


Link to post
Share on other sites
If I've 3 effects with each only one effect, I can execute all three "effect->Begin()" and all three "effect->End()" toghether and, always toghether, the three "effect->SetValue". The same is for the "CommitChanges" and "BeginPass" and "EndPass". As follow:


1 - CreateEffectFromFile in the initializzation of the application
1.1 - effect->GetTechnique(...)
1.2 - GetParameter ByName(...)
1.3 - m_technique=effect->SetTechnique(...)

2 - in the phase of rendering the 3D scene:
2.1 - effect->Begin(NULL, 0)
2.2 - effect->SetValue(shareVariable, valoreVector)
2.3 - effect->BeginPass(0) // I have "pass single" in each technique
2.4 - effect->CommitChanges()
2.5 - rendering of the 3D scene (Clear, BeginScene, render, EndScene, Present)
2.6 - effect->EndPass()
2.7 - effect->End()



The question is:
why I see that appear:

D3DX: ID3DXEffect::ApplyParameterBlock: Failed



and don't change the value in the Fx file also is "SetValue" return Ok handle ???

And I can't notice the change of color of my 3D object in fucntion esclusively of the share variable (variabile that I want to pass from CPlusPlus file to Fx file): in the Fx file, the value of share variable is ugual to zero and don't change.

Someone know why ???

Thanks for all.

Share this post


Link to post
Share on other sites
I've never used ApplyParameterBlock, so you can probably safely ignore that call. From your error, it looks like it's being called internally, and failing. Is the technique you're attempting to use valid on your graphics card? I'm not sure of any other reason why any part of the FX system would be failing.

You can set values at any time on the FX object. You can set values before you Begin the effect. You can set values before you BeginPass, which is useful if values change from pass to pass. You can set values after you BeginPass, which is useful when rendering many meshes using the same effect that require different values, textures, etc. CommitChanges only needs to be called if you've set variables after BeginPass. The ID3DXEffect gives the current values to the GPU when you call BeginPass or call CommitChanges.

Quote:
If I use only one effect with three technique, as in the code you have written, I set the share variable for the techinque A to 1.0f, B to 2.0f and C to 3.0f and not A, B and C to 3.0f ???

This was to demonstrate that if the variable is used across techniques, the value is global, and not specific to one technique. You can't just set a value per technique during initialization, you need to update the variable as you are rendering each object.

Share this post


Link to post
Share on other sites
Quote:
Original post by Namethatnobodyelsetook
I've never used ApplyParameterBlock, so you can probably safely ignore that call.


When I run the application, I can see (in a part of Visual Studio C++ .Net) the messagge "ApplyParameterBlock failed". The apllication run but don't change the color of the 3D object in function directly of the share variable.

Share this post


Link to post
Share on other sites
Quote:
Original post by Namethatnobodyelsetook
Is the technique you're attempting to use valid on your graphics card?


The technique are: "perPixel", "perVertex" e "vertexOnly":


technique perPixel
{
pass single
{
stateblock = <commonState>;
VertexShader = compile vs_1_1 PerPixelVS(world,view,proj);
PixelShader = compile ps_2_0 PerPixelPS(positionProbeLeftHand);
}
}
technique perVertex
{
pass single
{
stateblock = <commonState>;
VertexShader = compile vs_1_1 PerVertexVS(world,view,proj, positionProbeLeftHand);
PixelShader = compile ps_1_1 PerVertexPS();
}
}
technique vertexOnly
{
pass single
{
stateblock = <commonState>;
VertexShader = compile vs_1_1 PerVertexVS(world,view,proj, positionProbeLeftHand);
PixelShader = null;
}
}



as the same that I use in the code. And I've only one "pass" ("pass single") fr each technique.

Share this post


Link to post
Share on other sites
Quote:
Original post by Namethatnobodyelsetook

Quote:
If I use only one effect with three technique, as in the code you have written, I set the share variable for the techinque A to 1.0f, B to 2.0f and C to 3.0f and not A, B and C to 3.0f ???

This was to demonstrate that if the variable is used across techniques, the value is global, and not specific to one technique. You can't just set a value per technique during initialization, you need to update the variable as you are rendering each object.


So, I prefer to work with three effects, where each have only one technique, and not with one effect with three technique inside.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this