[Request] .material files explained

HypergripHypergrip SuspectGermany Join Date: 2002-11-23 Member: 9689Members, NS1 Playtester, Contributor
Working on my map I reached the point where I want to add some custom textures. The wiki page on materials is rather basic and I guess also outdated. Looking at the original .material files can be quite helpful, but there is some things I haven't completely figured out. Maybe you guys can help me. The goal would be to make a complete list for reference:

1.) A complete list of the possible values for "shader"

2.) A table/matrix that shows what shaders make use of which maps (and idicate which maps are required for the shader to work and which are optional)
drHSEUT.png
(note: the values in this example are of course not correct)

3.) A complete list of the possible values for "surface" including a short description of what effect they have (what effect DOES it have anyway?)

Comments

  • HowserHowser UK Join Date: 2010-02-08 Member: 70488Members, NS2 Playtester, Squad Five Blue, Reinforced - Shadow, WC 2013 - Shadow, Subnautica Playtester, Retired Community Developer
    edited May 2013
    Its bit of an undocumented system so alot of this is just me guessing, so it could be wrong.
    How the maps are used in a .material file is defined in the surface shader. The main surface shaders are kept in the Natural-selection 2/core/shaders directory and can be open and read with word.
    I generally use the model.surface_shader for most things this looks like this in a material file:

    shader = "shaders/Model.surface_shader"
    albedoMap = "materials/howser/artd_wallpans4.dds"
    normalMap = "materials/howser/artd_wallpans4_normal.dds"
    specularMap = "materials/howser/artd_wallpans4_spec.dds"
    surface = "metal"

    From looking at the surface shader itself I can conclude a few things:

    <inputs>
    <input name="albedoMap" type="texture" address="wrap" />
    <input name="normalMap" type="texture" address="wrap" />
    <input name="specularMap" type="texture" address="wrap" />

    So you can only reference a albedo, normal and specular in the .material.

    material.specular = specularGloss.rgb;
    material.gloss = specularGloss.a;
    The specular is a full rgb .dds so it can have colour (not tested this out in spark if it gives surfaces tints) if the .dds file has aN alpha channel it'll use that for a gloss map. This seems to be quite a common convention of the textures but I believe some shaders use the normal maps alpha for a specular, You'll have to check the .SURFACE_SHADERS and just make your list from there. It's really the only way to understand how the maps are being used.
    other inputs are
    Transparency =<input name="opacityMap" type="texture" address="wrap" />
    Light maps= <input name="emissiveMap" type="texture" address="wrap" srgb="true"/>

    Transparency is a strange one with spark, it seems the emissive texture defines how transparent areas are in some sort of additive method. Its odd, but if you want to make grates and such you should use a shader with:

    <param name="alphaTest">true</param>

    is the param that will force the alpha to be either invisible or fully opaque.

    So the only way to really know how they work is to go through all the surface shaders, there's probably only a few people will need to understand, I wouldn't bother with the odd ones for lava and what not.
    Hope that helps.
  • Rudy.czRudy.cz Join Date: 2012-02-13 Member: 145410Members
    Is there any way how to make a material opaque but not to cast shadows? I know we already tried to sort this one out and failed, but maybe you gained some new knowledge since :)
  • HowserHowser UK Join Date: 2010-02-08 Member: 70488Members, NS2 Playtester, Squad Five Blue, Reinforced - Shadow, WC 2013 - Shadow, Subnautica Playtester, Retired Community Developer
    not that I know of! you could make some model blocks then set cast shadows too off. But i'm guessing that won't work for the complex shapes you have without being a complete pain to manipulate into place.
  • SolarisSolaris Join Date: 2003-05-11 Member: 16213Members
    I movement a part of the .material, too? Or the shader? Or whatever?
    I've tried to figure out how the lava textures work, but failed. I thought just replacing the albedo map with a sand texture would give me falling sand (i wanted to recreate an hour glass). However in the editor it still just looked like the lava fall from refinery...
    So I take it "animating" a texture (the effect of the good old func_conveyer for starters) is more than playing around with Photoshop and editing the .material file? Any help greatly appreciated.
  • Rudy.czRudy.cz Join Date: 2012-02-13 Member: 145410Members
    Howser wrote: »
    not that I know of! you could make some model blocks then set cast shadows too off. But i'm guessing that won't work for the complex shapes you have without being a complete pain to manipulate into place.

    Is there any way how to export Spark mesh to 3D Max and back to Spark as a prop? I could do that with cel shade capsules when I will be finished with final shape.

  • InsaneInsane Anomaly Join Date: 2002-05-13 Member: 605Members, Super Administrators, Forum Admins, NS1 Playtester, Forum Moderators, NS2 Developer, Constellation, NS2 Playtester, Squad Five Blue, NS2 Map Tester, Subnautica Developer, Pistachionauts, Future Perfect Developer
    Howser basically has the right of it. The "shader" property references .surface_shader files. These are broadly divided into two categories: the core set found in core\shaders, and the NS2-specific set, which are typically single-use shaders created for visual effects like spore clouds or the Exo screen effect. These are found in a number of different places in the file system, typically alongside the cinematic or model files associated with them. If you want to maintain a list of all possible values for the shader property that would require a lot of work to maintain, since technically anybody could create any number of surface_shader files and distribute them in mods etc. However a good start would be to create and maintain a list of the core shaders, which should be enough for anyone interested in creating their own materials (or their own shaders for that matter).

    Unless I am thinking of something completely different, the "surface" property is what tells the game code what sort of impact sounds to play (e.g. footsteps, bullet hits and so on).

    The surface_shader files themselves are essentially XML files. Here you can define the inputs and other parameters of the shader. Inside the CDATA tag is the shader code itself, written in High Level Shader Language. This is the part that tells the renderer how to draw the surface, and how to use each individual texture map. If you're a texture artist I strongly encourage you to learn at least a little bit about how HLSL works; knowing the technical details of how your texture maps are used will help you to get the best out of them and even create your own shader effects.

    The majority of the interesting details on how the falling lava effects work, including the animation, are found in the lavafall.surface_shader file. Let's have a look:
    <shader>
    
    	<inputs>
    		<input name="glowpoints" type="texture" address="wrap" srgb="true"/>
    		<input name="noiseMap" type="texture" address="wrap" srgb="true"/>
    	
    
    
    	</inputs>	
    
    	<params>
    		<param name="osPosition">true</param>
    		<param name="wsPosition">true</param>
    		<param name="wsNormal">true</param>
    		<param name="vsNormal">true</param>
    		<param name="twoSided">false</param>
    		<param name="alphaTest">true</param>
    
    	</params>
    	
    	<code> 
    	<![CDATA[
    		void MaterialShader(in Material_Input input, inout Material material)
    		{
    		
    			const float3 tint = float3(.6, .1, .01);
    			
    			// Offset the position.
    			material.wsOffset = input.wsNormal * 0.03;
    			
    			
    			float3 ash = tex2D( glowpoints, input.texCoord  * float2( 0.8, .7) + float2(time * -.025, time * -.35) ).rgb;
    			float3 noise = tex2D( glowpoints, input.texCoord  * float2( 0.2, .5) + float2(time * .025, time * -0.25) ).rgb;
    			float3 noise2 = tex2D( noiseMap, input.texCoord  * float2( 0.3, 1.3) + float2(time * -.01, time * -.5) ).rgb;
    			float3 noise3 = tex2D( glowpoints, input.texCoord  * float2( 0.6, 2.1) + float2(time * -.02, time * -.8) ).rgb;
    
    			
    		
    
    			material.emissive = ( noise * noise2 + ash + noise3 ) * tint;
    			material.opacity = ( (noise + noise2 ) + noise3 + ash  ) * 10 ;
    			
    		}
    	]]>
    	</code>
    
    </shader>
    

    So the material file accepts a "glowpoints" and a "noisemap" texture map. From looking at the DDS files, and knowing that this shader is completely emissive I would say that the glowpoints map determines the points where the texture is bright (i.e. visible) and the noisemap adds a little more visual interest.

    We can see that the colour of the material is determined by the "tint" property (think of it like an RGB value where 1=255). We can also see that the animation is created by making adjustments to the texCoord value that include a "time" parameter.

    So how to go about making this look a little more sandy? Well first thing is to pick a more appropriate pair of texture maps by rewriting models\props\refinery\refinery_lava_01.material:
    shader = "cinematics/vfx_materials/sandfall.surface_shader"
    noiseMap = "materials/refinery_gravel_02.dds"
    glowpoints = "materials/effects/mesh_effects/waterfall_tile_02.dds"
    surface = "metal"
    

    I've copied the lavafall shader code into a new shader file called sandfall, located in the same spot. In this case, I'm only making one adjustment, to the tint value:
    const float3 tint = float3(.3, .2, .05);
    

    The end result is far from perfect but should provide an adequate starting point:

    mWkWBYD.jpg

    Obvious improvements can be made by creating more sandy-looking texture maps from scratch, rather than appropriating existing textures, and spending more time tweaking the tinting. If you were feeling adventurous you could rewrite the shader code further to get better results: at the moment it's repeatedly layering its input textures in a way that looks good for lava, but could be adjusted to look better for sand. Useful for this is the fact that the Editor (and I presume the Viewer) will hotload changes to materials and surface_shaders, with the caveats that it needs to restart to find new materials and it will take a little bit of time to recompile the shaders.
  • HowserHowser UK Join Date: 2010-02-08 Member: 70488Members, NS2 Playtester, Squad Five Blue, Reinforced - Shadow, WC 2013 - Shadow, Subnautica Playtester, Retired Community Developer
    Nice! I tried writing a few shaders myself but didn't really have too much luck since I was just trying to make a water texture I managed to combine elements from refract and scrolling albedo but the moment I tried to introduce any kind of specular properties it just went black. My assumption was we can't (at this point) have specular and transparent surfaces. That would explain while the glass doesn't look shiny ingame yet. I was mostly just stealing elements off other existing shaders with no real higher understanding of the system.

    Understanding the basic of modding existing shaders seems pretty straightforward, but I would like to gain some deeper understanding and be able to write my own from scratch at some point. You mentioned High Level Shader Language or HLSL. Is this a standardised system used on other engines? While I'm in no means in a rush to learn how to write my own shaders, but Its certainly something that interests me.
  • HypergripHypergrip Suspect Germany Join Date: 2002-11-23 Member: 9689Members, NS1 Playtester, Contributor
    Thank you for taking the time to shed some light on the shader stuff, Insane!
    I think I'll play around with in a bit, after all New Deimos needs flowing green space slime of doom :D

    Can anybody recommend a very basic HLSL tutorial?

    What would be a good place to get that list of core shader descriptions started? Last time I checked, mediawiki had terrible syntax for tables. (we could however just start with simple written descriptions)
  • InsaneInsane Anomaly Join Date: 2002-05-13 Member: 605Members, Super Administrators, Forum Admins, NS1 Playtester, Forum Moderators, NS2 Developer, Constellation, NS2 Playtester, Squad Five Blue, NS2 Map Tester, Subnautica Developer, Pistachionauts, Future Perfect Developer
    edited May 2013
    Howser wrote: »
    Nice! I tried writing a few shaders myself but didn't really have too much luck since I was just trying to make a water texture I managed to combine elements from refract and scrolling albedo but the moment I tried to introduce any kind of specular properties it just went black. My assumption was we can't (at this point) have specular and transparent surfaces. That would explain while the glass doesn't look shiny ingame yet. I was mostly just stealing elements off other existing shaders with no real higher understanding of the system.

    Understanding the basic of modding existing shaders seems pretty straightforward, but I would like to gain some deeper understanding and be able to write my own from scratch at some point. You mentioned High Level Shader Language or HLSL. Is this a standardised system used on other engines? While I'm in no means in a rush to learn how to write my own shaders, but Its certainly something that interests me.

    HLSL is Microsoft's shading language for use with Direct3D.

    We don't have proper transparency per se, what we tend to do is use emissive maps, which are drawn additively (rather like the "screen" blend mode in Photoshop), to simulate it. You can definitely combine specular and emissive maps on one material, so I don't know exactly what's going wrong there. Perhaps you could post your shader code?
    Hypergrip wrote: »
    Can anybody recommend a very basic HLSL tutorial?

    Honestly, I don't think there's a major need to use tutorials at this level; just open up a shader file that's close to what you want to achieve, make a copy, and play around with the values. It's pretty straightforward so you should be able to get a decent idea of how it works quite quickly.
  • HowserHowser UK Join Date: 2010-02-08 Member: 70488Members, NS2 Playtester, Squad Five Blue, Reinforced - Shadow, WC 2013 - Shadow, Subnautica Playtester, Retired Community Developer
    I was using the emissive map the same way the descent_glass shader uses it, as in the additive mask or whatever- the same transparent method you described. I tried to botch on some specular,fennel effect from some other shader and it just went opaque and black. I managed to get the basic effect right but without any reflections water just looks odd
    is there anyway to make transparent textures use specular maps?
    My assumption was that the engine just couldn't do that yet.
  • InsaneInsane Anomaly Join Date: 2002-05-13 Member: 605Members, Super Administrators, Forum Admins, NS1 Playtester, Forum Moderators, NS2 Developer, Constellation, NS2 Playtester, Squad Five Blue, NS2 Map Tester, Subnautica Developer, Pistachionauts, Future Perfect Developer
    Like I say, you should just be able to load a specular map into your shader. I can't say much more without seeing your code though.

  • HowserHowser UK Join Date: 2010-02-08 Member: 70488Members, NS2 Playtester, Squad Five Blue, Reinforced - Shadow, WC 2013 - Shadow, Subnautica Playtester, Retired Community Developer
    I don't have the broken version as i rolled it back to just a basic refract and tint shader which actually gave the best effect. I'll try reproduce the shader again tonight at work.
    I'd love to see a glass shader that worked with the same shine as opaque surfaces. Since I haven't seen it work I just assumed it wasn't possible.
Sign In or Register to comment.