pass variable

Started by
21 comments, last by Claudio 15 years, 2 months ago
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.
Advertisement
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.
Once you've created an effect from an .fx file, you can use ID3DXBaseEffect::SetFloat(Array) to set the value of your point.
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.

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 codeuniform extern float3 myVector;uniform extern float myFloat;//C++ codeD3DXVECTOR3 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.
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 codeuniform extern float3 myVector;uniform extern float myFloat;//C++ codeD3DXVECTOR3 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]
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.
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]
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 :)

Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!
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.

This topic is closed to new replies.

Advertisement