Shader Fragments (.vertex_fragment, .pixel_fragment) - emd4600/SporeModder-FX GitHub Wiki

Many shaders in Spore are not coded in a single .hlsl file directly. Instead, they are generated by combining different pieces of code, known as shader fragments. This allows to easily create multiple variations of a single shader (see Shader Builders) and avoids repeating code.

There are two types of shader fragments: one for vertex shaders and another for pixel shaders. Shader fragments are coded in HLSL, using the vs_3_0 and ps_3_0 versions.

Shader fragments are stored in the material_shader_fragments~ (0x40212002) folder, in a .smt file. To pack custom shader fragments, those must be placed inside a folder named 0x00000003.smt.unpacked. Inside, two types of files will be used:

  • .vertex_fragment: Fragments that can be used in vertex shaders.
  • .pixel_fragment: Fragments that can be used in pixel shaders.

Each file must only contain one shader fragment. The files use the ArgScript format common in many other Spore file formats.

A thing you must keep in mind if you want to pack your own shader fragents is that, since all mods would use the same folder (0x00000003.smt.unpacked), Spore will only read the fragments of one mod. Inside the pack you should also include all the fragments that Spore uses.

How code works in fragments

Fragments have two attributes, input and output, that specifiy which members are available to use in the code.

Fragments can specify HLSL code in two different ways:

  • declareCode: Here goes any functions, uniforms and samplers used by the fragment code. The Shader Data is also specified here.
  • code: The main code of the shader. The code used here will go inside the main function. There are three "special" variables that can be used: In (containing the input), Out (containing the output), and Current (containing the current data). Current is the most used, as it reflects the changes made by other shader fragments.

Both block types contain plain HLSL code, and are ended with a endCode statement (there are examples below).

In, Out and Current are structures whose members depend on the fragment (this is exaplined further below).

Vertex fragments

They are placed inside a vertexFragment block.

The input attribute can use the following members:

  • position: a float4 containing the vertex coordinates.
  • normal: a float4 containing the normal vector of the vertex
  • color: a float4, the verte color
  • color1: a float4
  • texcoord0: a float4, usually the UV coordinates used for texturing
  • texcoord1: a float4
  • texcoord2: a float4
  • texcoord3: a float4
  • texcoord4: a float4
  • texcoord5: a float4
  • texcoord6: a float4
  • texcoord7: a float4
  • blendIndices: an int4
  • blendWeights: a float4
  • pointSize: a float
  • position2: a float4
  • normal2: a float4
  • tangent: a float4
  • binormal: a float4
  • fog: a float
  • blendIndices2: an int4
  • blendWeights2: a float4

The output attribute can use any of the following members:

  • position: a float4
  • color: a float4
  • color1: a float4
  • fog: a float
  • pointSize: a float

A few things to consider:

  • The attributes available at Current are all the ones present in both the input and output.
  • Output can also use texcoords: you can specify the amount of texcoords used using the -texcoords option; there you must also specify the typeof texcoord variable (e.g. float2). For example, this will use 2 texcoords of type float3:
output position color -texcoords 2 float3
.
  • To access Out and Current texcoords you must do it like Current.texcoord<t0>. The texcoords there will be of the type specified in the -texcoords option.

An example of vertex fragment:

Attributes

input values...

The vertex attributes this shader receives as input. The values can be any of the members explained before.


output values... -texcoords texcoordCount texcoordType

The attributes that will be output by the shader.

  • values: Any of the members explaied before.
  • texcoordCount: The number of texcoords used at Current/Out by this fragment.
  • texcoordType: The type of texcoord used at Current/Out, any of the following: float2, float3, float4

declareCode
  # Your HLSL code
endCode

The declaration code, here you can specifiy uniforms, shader data, samplers, functions,...


code
  # Your HLSL code
endCode

The main code. This goes inside the main function of the shader. Here you can use In, Out and Current.

Pixel fragments

They are placed inside a pixelFragment block.

The input attribute can use any of the following members:

  • position: a float4
  • normal: a float3
  • tangent: a float3
  • binormal: a float3
  • color: a float4
  • color1: a float4
  • indices: a int4

The output attribute can use any of the following members:

  • color: a float4, the pixel color for the main render target
  • color1: a float4
  • color2: a float4
  • color3: a float4
  • depth: a float, used in the depth buffer

Pixel fragments can also receive texcoords as input. To do so, use the option -texcoords specifying the number of texcoords used. As before, you have to access them like Current.texcoord<t1>.

Pixel fragments can use a specific number of samplers. Similar to texcoords, these must be accessed with <s0>, such as Sampler<s2>.

Additionally, the texture attribute can be used to load a texture when using this fragment.

An example of pixel fragment:

Attributes

input values... -texcoords texcoordCount

The attributes this shader receives as input.

  • values: Any of the input members explained before.
  • texcoordCount: The number of texcoords used at In/Current by this fragment.

output values...

The attributes that will be output by the shader.

  • values: Any of the output members explaied before.

samplers samplerCount

Specifies the amount of generic samplers used by this fragment. These samplers are accessed with Sampler<s0>, Sampler<s1>,.... Apart from these, you can also specify other samplers in the declare code block.


texture resourceID -minFilter minFilter -mipFilter mipFilter -magFilter magFilter -addresses addresses...

Specifies a texture that will be loaded when this fragment is used.


declareCode
  # Your HLSL code
endCode

The declaration code, here you can specifiy uniforms, shader data, samplers, functions,...


code
  # Your HLSL code
endCode

The main code. This goes inside the main function of the shader. Here you can use In, Out and Current.

⚠️ **GitHub.com Fallback** ⚠️