Question about .surface_shader files
BeigeAlert
Texas Join Date: 2013-08-08 Member: 186657Members, Super Administrators, Forum Admins, NS2 Developer, NS2 Playtester, Squad Five Blue, Squad Five Silver, NS2 Map Tester, Reinforced - Diamond, Reinforced - Shadow, Subnautica Playtester, Pistachionauts
in Modding
Is there any documentation on these? I'd like to find a way to get the eye position or view vector or something so I can try to make a parallax occlusion shader, but I don't know what data is passed to the shader... I saw Insane's post a while back, but it didn't answer my question. Despite looking a heck of a lot like hlsl code... it seems the only function of these files is to prepare the maps (ie transforming the normal maps rgb channels from a range of 0.0-1.0 to a range of -1.0 to 1.0) and pass them onto the REAL shader... wherever that is... I figure that stuff is buried deep in the engine and we can't get to it.
Comments
I looked at the others, none of them have any mention of anything other than material files, at least not the ones I saw. Yea the hlsl files have that... but I can't very well set a .material file to use an hlsl can I? ...................wait, can I?
For example, look at the "ns2\shaders\glass_refract.surface_shader"... the last line of the shader code says "material.ssDistortion = ......" etc. well that's a pretty convenient option to have! Almost as if it's defined elsewhere what to do with this mysterious "ssDistortion".
I guess what I really want to get at is what values can I pull from the "Material_Input"
EDIT: AHA! "core\renderer\deferred.hlsl" has got it!
But for a .material you have to use a .surface_shader, right?
SamusDroid was referring to a ScreenFX file(s). I don't think this will give you want you want because ScreenFX's are basically like adding an additional Layer to the final rendering pass. Using a screenfx shader would not give you access to a specific material's UV coordinates and normal map. In order to add PO to a material you will need that material's data, in addition to the player's camera data (dot product of the eye position, etc).
The ScreenFX files are essentially working with a Frame Buffer to achieve their intended effects. This is initialized (from Lua) by creating an additional Camera object. You can feed parameters to a ScreenFX but only basic data types. In ALL of the shaders, you cannot pass the following data types: Float(2,3, or 4) Vector, Color, Matrix, nor String. You are basically limited to only passing single Float values to shaders via the parameters (passing data from Lua). Take a look at HiveVision or EquipmentOutline to see an example of this.
The downside you're looking at is this: ScreenFX reference the Player's Camera only; the world objects use the material system. The two do not cross-talk and it's a serious PITA to get data back-n-forth between the two (essentially Lua is the only available transfer layer). Using Lua for something like this is very slow and honestly not and option.
I'm fairly certain you would need to modify the material data structure (defined in the core/renderer/Deferred.render_setup file) to either have access to or be supplied the Vector data of the player's Camera. How specifically that is done, I don't know exactly. I never found a concise bridge between the two during my rummaging. Once you have this data, you would then need to create a new *.surface_shader that runs the PO process. Long story short, this will be a very major change to the current rendering process and be a bitch to do.
Regardless of difficulties, this is quite interesting. I'd love to see how this effect looks with the current art style of NS2.
Yea I figured screen fx wasn't what I was after anyways.
Now I think I *MIGHT* have found what I needed in "core\renderer\Deferred.hlsl". There's a struct for "Material_Input" which is the object type that is passed to the .surface_shader. This has the "texCoord" float2 that contains the texture coordinates from the surface, BUT I notice below it, it ALSO has float3 wsPosition (world space position, I assume), float3 wsNormal (world space normals I assume), float3 vsPosition (view-space position I assume), float3 vsNormal, float3 vsBinormal, float3 vsTangent, and three others I don't have a clue about (float3 osPosition, float3 wsOrigin, float4 shaderParam)
The only thing is, unlike float2 texCoord and float4 color, all those other parameters are sandwiched between some kind of if statements, ie world-space position is surrounded by "#ifdef PARAM_wsPosition" and "#endif" I'm not sure exactly what #ifdef means, but my guess is that it indicates that these parameters might not exist for every material... in which case I'm royally screwed.
Those are determined by the <params> tag in the surface_shader file if I recall correctly. Regardless, you will have to create a new surface_shader to do what you need, and then point all the material files to use said shader. Nice thing is though, the material files are tiny and CAN be overridden by mods. So, you could conceivably overwrite all the materials for the entire game and the mod size would still be very small.
Take a look at shaders/ExoMinigunView.surface_shader file for an example of the <params> tag.
There is an important limitation to keep in mind however. Since they added in OpenGL and DX11 support, the number of <input>s allowed is now a fixed number. If I recall correctly, that limit is 12, but don't quote me on that.
Cool I'll check it out. What I'm planning is just modifying the level.surface_shader to use an alpha channel from the normal map (otherwise never has an alpha) as the depth map for the parallax effect... or I might modify the model.surface_shader instead... that one let's you define a glossy map!
I've already got a few custom textures that will benefit greatly from a PO shader.
One other question I have... is there a way to check the client's graphics settings? If they're on a low end machine, we definitely don't want this turned on... it's quite a bit of extra processing.
Downside to checking for this is you have to override the GUI script. There is currently no good way to do so, even with the hooks (modding framework). The GUIScript class would need to be overridden in order to give you said hooks. I believe Shine uses this method; however, this means it will require Lua code to take this approach.
Personally, I would skip the Lua client check entirely. Just make it either a sub-mod of your level or just part of the base package. Well, I assume this is for the map(s?) you've been working on.
If you are going to use the normal map, here is a simple way to grey-scale any texture you're working with in a Surface Shader. Ideally, your displacement map would be a 8bit grey-scale of the albedo map. Well, not exactly considering its just a height map but you get the idea.
Darn, that's a shame. It really kinda limits what I can do, because PO mapping is a pretty computationally intensive process... if there's no way to check options to turn it off... I'll have to drastically scale back where I use this thing.
I was going to use the alpha channel of the normal map for the displacement, ie: float d = (tex2D(normalMap, input.texCoord).a *2 -1) *dispAmt;
Simple example: You cannot use the #include directive with in surface_shader files <code> tag. That means anything that could be (or rather should be) treated like a library or common function set has to be duplicated in each surface_shader you create. I really wish this would be changed because it could serve to reduce the duplication of code quite a bit. Not too mention, make the 'Optimize Shaders' process faster and the precaching of shaders faster. Well, that's assuming the #include directive would be considered shared and referenced memory.
Anyways, I'm not sure you'll be able to achieve the effect you want using the Normal map's alpha channel. I'm pretty sure that value will always be 1. When reading a texture, tex2D(), it will look at the actual alpha value in that texture. Unless you're going to bake your own normal maps and modify them (I.e. adding actual alpha values), then I suspect this won't work as expected.
Take a look at this section of GPU Gems 3 book. It's a different technique than I think you were planning on using, but it covers the same issues.
http://developer.download.nvidia.com/books/gpu_gems_3/samples/gems3_ch18.pdf
Another worthy read, but no where near the same detail. Although, this is more inline with what data we have available to surface shaders:
http://developer.amd.com/wordpress/media/2012/10/Tatarchuk-POM.pdf
None of the built-in textures have alpha channels for normal maps, correct. This shader is only for my own materials (and I suppose anybody else's who wants to make them), in which I will be including a depth map in the alpha channel.
I don't remember which but there is a file which has cases for all the options.