Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

#Actuald k h

Posted 15 May 2012 - 04:24 AM

The only two functions in an .FX file that are guaranteed to be called are the two functions that you list at the end (in "pass P0"), "vertexShader" and "pixelShader" in your case. You can, however, have any number of helper functions etc. above these and call them from either of the two 'main' functions (if you want to call them that).

It's important to keep in mind how the data flows through the shader - I personally use four structs in my HLSL shaders to keep the code readable, your example shader uses only two (the output structs, these are mandatory). For the input to both vertex and pixel shader it just lists the variables as function parameters. I replace that mess with two additional structs so in total I have "vertex_in", "vertex_out", "pixel_in" and "pixel_out", each a struct holding exactly the data that the vertex or pixel shader passes in or out.

This is how the two vertex shader structs would look like for your shader:

[source lang="cpp"]struct InputVS{ float3 posW : POSITION0,  // we assume terrain geometry is specified float3 normalW [font=courier new,courier,monospace]: NORMAL0, // directly in world space float2 tex0   : TEXCOORD0[/font]};struct OutputVS{ float4 posH : POSITION0; float2 tiledTexC : TEXCOORD0; float2 nonTiledTexC : TEXCOORD1; float  shade : TEXCOORD2;};[/source]

You don't have to compile the shader yourself before running your game, D3DX can do this for you via "D3DXCreateEffectFromFile". Make sure to read any error messages if that function (and the shader compile) fails, it'll tell you when there's an error in your shader and where it is!

This is how I load shaders in my games:

[source lang="cpp"]// NOTE: remove the space wherever there should be two < right after another! I had to include these because otherwise the code wouldn't show up properly in my post. Sorry for that!void Shader::CreateFromFile ( std::string filename ){ ID3DXBuffer *error_buffer = NULL; if ( FAILED ( D3DXCreateEffectFromFile ( window->GetDevice ( ), filename.c_str ( ), NULL, NULL, SHADER_COMPILE_FLAGS, NULL, &effect, &error_buffer ) ) ) { std::stringstream s; if ( !error_buffer ) s < < "Failed to load shader '" < < filename.c_str ( ) < < "'..."; else { s < < "Failed to compile shader '" < < filename.c_str ( ) < < "'..." < < std::endl < < std::endl; s < < "The following errors were encountered during compilation:" < < std::endl < < std::endl; s < < ( const char *) error_buffer->GetBufferPointer ( ); } Error ( s.str ( ) ); window->Quit ( ); return; } if ( !effect ) { std::stringstream s; s < < "Failed to create effect from file '" < < filename.c_str ( ) < < "'..."; Error ( s.str ( ) ); window->Quit ( ); return; } if ( error_buffer ) error_buffer->Release ( ); delete error_buffer;}[/source]

It's practical this way because I can have the .FX file open in a text editor or my compiler IDE, make a change to the shader and run the .exe again, no need to re-compile or run the HLSL compiler or anything.

Apart from that, I don't quite get your texture blending plan quite yet. The easiest way to do this usually is have the blendmap be just different shades of gray where the brightness of a pixel determines how much of texture A or texture B is mixed in. Looks like the shader you posted should do exactly that!

That's about all I can think of, hope this helps! Posted Image

#10d k h

Posted 15 May 2012 - 04:24 AM

The only two functions in an .FX file that are guaranteed to be called are the two functions that you list at the end (in "pass P0"), "vertexShader" and "pixelShader" in your case. You can, however, have any number of helper functions etc. above these and call them from either of the two 'main' functions (if you want to call them that).

It's important to keep in mind how the data flows through the shader - I personally use four structs in my HLSL shaders to keep the code readable, your example shader uses only two (the output structs, these are mandatory). For the input to both vertex and pixel shader it just lists the variables as function parameters. I replace that mess with two additional structs so in total I have "vertex_in", "vertex_out", "pixel_in" and "pixel_out", each a struct holding exactly the data that the vertex or pixel shader passes in or out.

This is how the two vertex shader structs would look like for your shader:

[source lang="cpp"]struct InputVS{ float3 posW : POSITION0,  // we assume terrain geometry is specified float3 normalW [font=courier new,courier,monospace]: NORMAL0, // directly in world space float2 tex0   : TEXCOORD0[/font]};struct OutputVS{ float4 posH : POSITION0; float2 tiledTexC : TEXCOORD0; float2 nonTiledTexC : TEXCOORD1; float  shade : TEXCOORD2;};[/source]

You don't have to compile the shader yourself before running your game, D3DX can do this for you via "D3DXCreateEffectFromFile". Make sure to read any error messages if that function (and the shader compile) fails, it'll tell you when there's an error in your shader and where it is!

This is how I load shaders in my games:

[source lang="cpp"]// NOTE: remove the space wherever there should be two < right after another! I had to include these because otherwise the code wouldn't show up properly in my post. Sorry for that!void Shader::CreateFromFile ( std::string filename ){ ID3DXBuffer *error_buffer = NULL; if ( FAILED ( D3DXCreateEffectFromFile ( window->GetDevice ( ), filename.c_str ( ), NULL, NULL, SHADER_COMPILE_FLAGS, NULL, &effect, &error_buffer ) ) ) { std::stringstream s; if ( !error_buffer ) s < < "Failed to load shader '" < < filename.c_str ( ) < < "'..."; else { s < < "Failed to compile shader '" < < filename.c_str ( ) < < "'..." < < std::endl < < std::endl; s < < "The following errors were encountered during compilation:" < < std::endl < < std::endl; s < < ( const char *) error_buffer->GetBufferPointer ( ); } Error ( s.str ( ) ); window->Quit ( ); return; } if ( !effect ) { std::stringstream s; s < < "Failed to create effect from file '" < < filename.c_str ( ) < < "'..."; Error ( s.str ( ) ); window->Quit ( ); return; } if ( FAILED ( effect->SetTechnique ( "EntryPoint" ) ) ) { std::stringstream s; s < < "Failed to set technique for effect '" < < filename.c_str ( ) < < "'..."; Error ( s.str ( ) ); window->Quit ( ); return; } if ( error_buffer ) error_buffer->Release ( ); delete error_buffer;}[/source]

It's practical this way because I can have the .FX file open in a text editor or my compiler IDE, make a change to the shader and run the .exe again, no need to re-compile or run the HLSL compiler or anything.

Apart from that, I don't quite get your texture blending plan quite yet. The easiest way to do this usually is have the blendmap be just different shades of gray where the brightness of a pixel determines how much of texture A or texture B is mixed in. Looks like the shader you posted should do exactly that!

That's about all I can think of, hope this helps! Posted Image

#9d k h

Posted 15 May 2012 - 04:22 AM

The only two functions in an .FX file that are guaranteed to be called are the two functions that you list at the end (in "pass P0"), "vertexShader" and "pixelShader" in your case. You can, however, have any number of helper functions etc. above these and call them from either of the two 'main' functions (if you want to call them that).

It's important to keep in mind how the data flows through the shader - I personally use four structs in my HLSL shaders to keep the code readable, your example shader uses only two (the output structs, these are mandatory). For the input to both vertex and pixel shader it just lists the variables as function parameters. I replace that mess with two additional structs so in total I have "vertex_in", "vertex_out", "pixel_in" and "pixel_out", each a struct holding exactly the data that the vertex or pixel shader passes in or out.

This is how the two vertex shader structs would look like for your shader:

[source lang="cpp"]struct InputVS{ float3 posW : POSITION0,  // we assume terrain geometry is specified float3 normalW [font=courier new,courier,monospace]: NORMAL0, // directly in world space float2 tex0   : TEXCOORD0[/font]};struct OutputVS{ float4 posH : POSITION0; float2 tiledTexC : TEXCOORD0; float2 nonTiledTexC : TEXCOORD1; float  shade : TEXCOORD2;};[/source]

You don't have to compile the shader yourself before running your game, D3DX can do this for you via "D3DXCreateEffectFromFile". Make sure to read any error messages if that function (and the shader compile) fails, it'll tell you when there's an error in your shader and where it is!

This is how I load shaders in my games:

[source lang="cpp"]// NOTE: remove the space wherever there should be two < right after another! I had to include these because otherwise the code wouldn't show up properly in my post. Sorry for that!void Shader::CreateFromFile ( std::string filename ){ ID3DXBuffer *error_buffer = NULL; if ( FAILED ( D3DXCreateEffectFromFile ( window->GetDevice ( ), filename.c_str ( ), NULL, NULL, SHADER_COMPILE_FLAGS, NULL, &effect, &error_buffer ) ) ) { std::stringstream s; if ( !error_buffer ) s < < "Failed to load shader '" < < filename.c_str ( ) < < "'..."; else { s < < "Failed to compile shader '" < < filename.c_str ( ) << "'..." < < std::endl < < std::endl; s < < "The following errors were encountered during compilation:" < < std::endl < < std::endl; s < < ( const char *) error_buffer->GetBufferPointer ( ); } Error ( s.str ( ) ); window->Quit ( ); return; } if ( !effect ) { std::stringstream s; s < < "Failed to create effect from file '" < < filename.c_str ( ) < < "'..."; Error ( s.str ( ) ); window->Quit ( ); return; } if ( FAILED ( effect->SetTechnique ( "EntryPoint" ) ) ) { std::stringstream s; s < < "Failed to set technique for effect '" < < filename.c_str ( ) < < "'..."; Error ( s.str ( ) ); window->Quit ( ); return; } if ( error_buffer ) error_buffer->Release ( ); delete error_buffer;}[/source]

It's practical this way because I can have the .FX file open in a text editor or my compiler IDE, make a change to the shader and run the .exe again, no need to re-compile or run the HLSL compiler or anything.

Apart from that, I don't quite get your texture blending plan quite yet. The easiest way to do this usually is have the blendmap be just different shades of gray where the brightness of a pixel determines how much of texture A or texture B is mixed in. Looks like the shader you posted should do exactly that!

That's about all I can think of, hope this helps! Posted Image

#8d k h

Posted 15 May 2012 - 04:22 AM

The only two functions in an .FX file that are guaranteed to be called are the two functions that you list at the end (in "pass P0"), "vertexShader" and "pixelShader" in your case. You can, however, have any number of helper functions etc. above these and call them from either of the two 'main' functions (if you want to call them that).

It's important to keep in mind how the data flows through the shader - I personally use four structs in my HLSL shaders to keep the code readable, your example shader uses only two (the output structs, these are mandatory). For the input to both vertex and pixel shader it just lists the variables as function parameters. I replace that mess with two additional structs so in total I have "vertex_in", "vertex_out", "pixel_in" and "pixel_out", each a struct holding exactly the data that the vertex or pixel shader passes in or out.

This is how the two vertex shader structs would look like for your shader:

[source lang="cpp"]struct InputVS{ float3 posW : POSITION0,  // we assume terrain geometry is specified float3 normalW [font=courier new,courier,monospace]: NORMAL0, // directly in world space float2 tex0   : TEXCOORD0[/font]};struct OutputVS{ float4 posH : POSITION0; float2 tiledTexC : TEXCOORD0; float2 nonTiledTexC : TEXCOORD1; float  shade : TEXCOORD2;};[/source]

You don't have to compile the shader yourself before running your game, D3DX can do this for you via "D3DXCreateEffectFromFile". Make sure to read any error messages if that function (and the shader compile) fails, it'll tell you when there's an error in your shader and where it is!

This is how I load shaders in my games:

[source lang="cpp"]// NOTE: remove the space in between every '< <' please! I had to include these because otherwise the code wouldn't show up properly in my post. Sorry for that!void Shader::CreateFromFile ( std::string filename ){ ID3DXBuffer *error_buffer = NULL; if ( FAILED ( D3DXCreateEffectFromFile ( window->GetDevice ( ), filename.c_str ( ), NULL, NULL, SHADER_COMPILE_FLAGS, NULL, &effect, &error_buffer ) ) ) { std::stringstream s; if ( !error_buffer ) s < < "Failed to load shader '" < < filename.c_str ( ) < < "'..."; else { s < < "Failed to compile shader '" < < filename.c_str ( ) << "'..." < < std::endl < < std::endl; s < < "The following errors were encountered during compilation:" < < std::endl < < std::endl; s < < ( const char *) error_buffer->GetBufferPointer ( ); } Error ( s.str ( ) ); window->Quit ( ); return; } if ( !effect ) { std::stringstream s; s < < "Failed to create effect from file '" < < filename.c_str ( ) < < "'..."; Error ( s.str ( ) ); window->Quit ( ); return; } if ( FAILED ( effect->SetTechnique ( "EntryPoint" ) ) ) { std::stringstream s; s < < "Failed to set technique for effect '" < < filename.c_str ( ) < < "'..."; Error ( s.str ( ) ); window->Quit ( ); return; } if ( error_buffer ) error_buffer->Release ( ); delete error_buffer;}[/source]

It's practical this way because I can have the .FX file open in a text editor or my compiler IDE, make a change to the shader and run the .exe again, no need to re-compile or run the HLSL compiler or anything.

Apart from that, I don't quite get your texture blending plan quite yet. The easiest way to do this usually is have the blendmap be just different shades of gray where the brightness of a pixel determines how much of texture A or texture B is mixed in. Looks like the shader you posted should do exactly that!

That's about all I can think of, hope this helps! Posted Image

#7d k h

Posted 15 May 2012 - 04:21 AM

The only two functions in an .FX file that are guaranteed to be called are the two functions that you list at the end (in "pass P0"), "vertexShader" and "pixelShader" in your case. You can, however, have any number of helper functions etc. above these and call them from either of the two 'main' functions (if you want to call them that).

It's important to keep in mind how the data flows through the shader - I personally use four structs in my HLSL shaders to keep the code readable, your example shader uses only two (the output structs, these are mandatory). For the input to both vertex and pixel shader it just lists the variables as function parameters. I replace that mess with two additional structs so in total I have "vertex_in", "vertex_out", "pixel_in" and "pixel_out", each a struct holding exactly the data that the vertex or pixel shader passes in or out.

This is how the two vertex shader structs would look like for your shader:

[source lang="cpp"]struct InputVS{ float3 posW : POSITION0,  // we assume terrain geometry is specified float3 normalW [font=courier new,courier,monospace]: NORMAL0, // directly in world space float2 tex0   : TEXCOORD0[/font]};struct OutputVS{ float4 posH : POSITION0; float2 tiledTexC : TEXCOORD0; float2 nonTiledTexC : TEXCOORD1; float  shade : TEXCOORD2;};[/source]

You don't have to compile the shader yourself before running your game, D3DX can do this for you via "D3DXCreateEffectFromFile". Make sure to read any error messages if that function (and the shader compile) fails, it'll tell you when there's an error in your shader and where it is!

This is how I load shaders in my games:

[source lang="cpp"]// NOTE: remove the spaces in between every '< <'! I had to include these because otherwise the code wouldn't show up properly in my post. Sorry for that!void Shader::CreateFromFile ( std::string filename ){ ID3DXBuffer *error_buffer = NULL; if ( FAILED ( D3DXCreateEffectFromFile ( window->GetDevice ( ), filename.c_str ( ), NULL, NULL, SHADER_COMPILE_FLAGS, NULL, &effect, &error_buffer ) ) ) { std::stringstream s; if ( !error_buffer ) s < < "Failed to load shader '" << filename.c_str ( ) << "'..."; else { s < < "Failed to compile shader '" << filename.c_str ( ) << "'..." << std::endl << std::endl; s < < "The following errors were encountered during compilation:" << std::endl << std::endl; s < < ( const char *) error_buffer->GetBufferPointer ( ); } Error ( s.str ( ) ); window->Quit ( ); return; } if ( !effect ) { std::stringstream s; s < < "Failed to create effect from file '" << filename.c_str ( ) << "'..."; Error ( s.str ( ) ); window->Quit ( ); return; } if ( FAILED ( effect->SetTechnique ( "EntryPoint" ) ) ) { std::stringstream s; s < < "Failed to set technique for effect '" << filename.c_str ( ) << "'..."; Error ( s.str ( ) ); window->Quit ( ); return; } if ( error_buffer ) error_buffer->Release ( ); delete error_buffer;}[/source]

It's practical this way because I can have the .FX file open in a text editor or my compiler IDE, make a change to the shader and run the .exe again, no need to re-compile or run the HLSL compiler or anything.

Apart from that, I don't quite get your texture blending plan quite yet. The easiest way to do this usually is have the blendmap be just different shades of gray where the brightness of a pixel determines how much of texture A or texture B is mixed in. Looks like the shader you posted should do exactly that!

That's about all I can think of, hope this helps! Posted Image

#6d k h

Posted 15 May 2012 - 04:18 AM

The only two functions in an .FX file that are guaranteed to be called are the two functions that you list at the end (in "pass P0"), "vertexShader" and "pixelShader" in your case. You can, however, have any number of helper functions etc. above these and call them from either of the two 'main' functions (if you want to call them that).

It's important to keep in mind how the data flows through the shader - I personally use four structs in my HLSL shaders to keep the code readable, your example shader uses only two (the output structs, these are mandatory). For the input to both vertex and pixel shader it just lists the variables as function parameters. I replace that mess with two additional structs so in total I have "vertex_in", "vertex_out", "pixel_in" and "pixel_out", each a struct holding exactly the data that the vertex or pixel shader passes in or out.

This is how the two vertex shader structs would look like for your shader:

[source lang="cpp"]struct InputVS{ float3 posW : POSITION0,  // we assume terrain geometry is specified float3 normalW [font=courier new,courier,monospace]: NORMAL0, // directly in world space float2 tex0   : TEXCOORD0[/font]};struct OutputVS{ float4 posH : POSITION0; float2 tiledTexC : TEXCOORD0; float2 nonTiledTexC : TEXCOORD1; float  shade : TEXCOORD2;};[/source]

You don't have to compile the shader yourself before running your game, D3DX can do this for you via "D3DXCreateEffectFromFile". Make sure to read any error messages if that function (and the shader compile) fails, it'll tell you when there's an error in your shader and where it is!

This is how I load shaders in my games:

[source lang="cpp"]void Shader::CreateFromFile ( std::string filename ){ ID3DXBuffer *error_buffer = NULL; if ( FAILED ( D3DXCreateEffectFromFile ( window->GetDevice ( ), filename.c_str ( ), NULL, NULL, SHADER_COMPILE_FLAGS, NULL, &effect, &error_buffer ) ) ) { std::stringstream s; if ( !error_buffer ) s << "Failed to load shader '" << filename.c_str ( ) << "'..."; else { s << "Failed to compile shader '" << filename.c_str ( ) << "'..." << std::endl << std::endl; s << "The following errors were encountered during compilation:" << std::endl << std::endl; s << ( const char *) error_buffer->GetBufferPointer ( ); } Error ( s.str ( ) ); window->Quit ( ); return; } if ( !effect ) { std::stringstream s; s << "Failed to create effect from file '" << filename.c_str ( ) << "'..."; Error ( s.str ( ) ); window->Quit ( ); return; } if ( FAILED ( effect->SetTechnique ( "EntryPoint" ) ) ) { std::stringstream s; s << "Failed to set technique for effect '" << filename.c_str ( ) << "'..."; Error ( s.str ( ) ); window->Quit ( ); return; } if ( error_buffer ) error_buffer->Release ( ); delete error_buffer;}[/source]

It's practical this way because I can have the .FX file open in a text editor or my compiler IDE, make a change to the shader and run the .exe again, no need to re-compile or run the HLSL compiler or anything.

Apart from that, I don't quite get your texture blending plan quite yet. The easiest way to do this usually is have the blendmap be just different shades of gray where the brightness of a pixel determines how much of texture A or texture B is mixed in. Looks like the shader you posted should do exactly that!

That's about all I can think of, hope this helps! Posted Image

PARTNERS