For a brief tutorial on shaders see: https://github.com/mtijanic/nwnee-shader-tutorials
NWN:EE shaders are the Open GL Shading Language (GLSL) code blocks which are run by the game to render scenes. This page specifies the usable portions (ie uniforms, defines) for writing your own ones.
Shader Types
There are a few types of shader which run at different points in the rendering process.
As an editor, you have access to three types of shader.
Vertex Shader
This shader helps a scene determine where vertices should be relative to where the client is looking.
Everything rendered between the vertices needs to have this part first so it knows where those vertices will be and can then interpolate what screen pixel will see what texture pixels.
Everything between vertices will be handled by a fragment shader later after getting base information from this shader.
Vertex shaders handle model transforms, such as those passed in from the toolset, those applied by runtime transform effects, and the bones inside skinned models.
Vertex shaders also handle base lighting functions related to how that vertex is oriented with respect to any given light.
Before a vertex shader is run on any given vertex in a mesh, the meshes available are first clipped to the view prism. This is a shape which includes what the engine expects you can see within your visible range, up, down, left and right. Anything not in that view prism will be omitted from the vertex shader for the scene, so you cannot shift distant objects into the view of a player if they're previously clipped. While you can modify how the content in the view prism is drawn, you cannot modify the view prism from inside the vertex shader. Any attempt to see beyond the hardcoded view prism will result in your final scene missing objects that were clipped away.
Each mesh will run its own copy of a vertex shader, which will differ based on what is being rendered. By default, different mesh types will be sent through specific shaders.
You can modify which vertex shader is used via material files. To change the vertex shader, use the command "customshadervs" followed by the name of the shader you want to use.
If you supply a custom shader command in a material file, then both fragment and vertex shaders must be explicitly supplied.
Fragment Shader
You can think of your screen as a 3D array. You have screen width X screen height X screen depth.
Each mesh or particle anywhere in the depth that needs to be considered for drawing is a fragment.
The fragment shader gets position and base lighting information from the vertex shader, and then finishes most of the rest of drawing.
Fragment shaders only have access to vertex information which is passed forward to them by their vertex shader counterpart.
Each fragment will run its own copy of a fragment shader, which will differ based on what is being rendered. By default, different mesh and particle types will be sent through specific shaders.
You can modify which shaders meshes are sent through using material files. To change the fragment shader, use the command "customshaderfs" followed by the name of the shader you want to use.
If you supply a custom shader command in a material file, then both fragment and vertex shaders must be explicitly supplied.
Post Processing Shader
Post Processing is what happens after the scene is built with the fragment shaders. This is where you add final touches to the final image.
This is actually a series of connected shader chunks which you can enable/disable. The standard functions currently include:
- Sharpen
- Vibrance
- Depth of Field Blurring
- Screen Space Ambient Occlusion (SSAO)
- Dynamic Contrast
- Gamma Correction
- Special Filters (ex. Toon Filter)
There is only one post processing shader that is used by the whole screen, so cannot define a separate post processing shader for each material.
Post processing shaders do not have access to vertex and fragment information from the individual meshes and particles. They only access the current frame being finished, or the frame buffers of a previous frame.
Standard Uniform Attributes Available to Shaders
These are available and passed from the engine to the shader files via. specifically named uniforms. Most are defined in an existing include file (that are usually chained together), thus don't need a new definition, but some are not defined and will be marked as such. See Shaders for how uniforms are defined (with the attribute keyword) and used.
These lists are ordered roughly by type.
Basic Uniforms
| Uniform | Type | Located In | Compatibility | Purpose and Notes |
|---|---|---|---|---|
| globalColor | lowp vec4 | A large amount of shader files | The default color when one is otherwise not supplied | |
vPos | vec4 | inc_common | Vertex position in world space. Prior to 1.89.8193.37 it is the position in object space instead. | |
vTcIn | vec2 | inc_common | Texture coordinates for current texture. | |
vTcLn1 vTcLn2 vTcLn3 | vec2 (but needs testing) | Not defined | Previously only one texture coordinate stream (named “tverts” in the model file) was supported per mesh. We now support three additional texture coordinate streams, named “tverts1”, “tverts2”, and “tverts3”, which will be linked to any shaders with the named attributes “vTcIn1”, “vTcIn2”, and “vTcIn3”. | |
vColor | vec4 | inc_common | Active colour for the vertex. | |
vCustomColor | vec4 | Not defined | The colors attribute of the trimesh MDL files. Only RGB is defined in the MDL spec (3 vectors). This can be used for colouring, obviously, but also for other data since the game and shaders don't use it by default. You must define this yourself (see Shaders). | |
vNormal | vec3 | inc_common | Current vertex untransformed normal. | |
vTangent | vec3 | inc_transform | Tangent | |
fHandedness | float | inc_transform | ||
| fAlphaDiscardValue | float | inc_common | Contains the minimum alpha level to draw. Any value below this will be dropped, greatly speeding up rendering of transparent objects as they stack up over distance. | |
| subvariant | int | inc_common | 1.88.8193.36 | Framebuffer usage, mainly used for multiple passes with the same shader. See usage in fsfbbloom.shd and fsfssao.shd |
bboxMin bboxMax | vec3 | inc_common | Give access to local bounds of a given rendered mesh in xyz. | |
particleSoftness | float | fsparticle | Not mobile | Replaces older particle uniforms |
fProjectionFrontal | float | vs_beamvol vs_shadowvol | ||
| projectionSource | vec4 | vs_beamvol vs_shadowvol | ||
| projectionWorldZClip | float | vs_beamvol vs_shadowvol |
Parameter Uniforms
These are multiple uniforms basically compressed into one uniform for optimisation purposes. They used to be separate uniforms.
| Uniform | Type | Located In | Compatibility | Purpose and Notes |
|---|---|---|---|---|
| screenParams | highp vec2 | inc_common | contains XY = [screenWidth, screenHeight]. #define screenWidth (screenParams.x) #define screenHeight (screenParams.y) | |
| pixelParams | highp vec3 | inc_common | contains XYZ = [invScreenWidth, invScreenHeight, fAspectRatio] and XY = vPixelSize #define vPixelSize (pixelParams.xy) #define invScreenWidth (pixelParams.x) #define invScreenHeight (pixelParams.y) #define fAspectRatio (pixelParams.z) | |
| clipParams | highp vec3 | inc_common | contains XYZ = [nearClip, farClip, fDepthToLinearModifier] #define nearClip (clipParams.x) #define farClip (clipParams.y) #define fDepthToLinearModifier (clipParams.z) // This is (1-near / far) |
Matrix Uniforms
| Uniform | Type | Located In | Compatibility | Purpose and Notes |
|---|---|---|---|---|
| m_mvp | highp mat4 | inc_common | matrix for converting from model to screen projection | |
| m_mv | highp mat4 | inc_common | matrix for converting from model to view | |
| m_m | mat4 | various / post processing | Matrix for converting from model to world coordinates | |
| m_proj | highp mat4 | inc_common | matrix for converting from view to screen projection | |
| m_proj_inv | highp mat4 | inc_common | matrix for converting from screen projection to view | |
| m_vp | highp mat4 | Not defined | maxtrix for converting from screen projection to | |
| m_vp_inv | highp mat4 | inc_common | ||
| m_view_inv | highp mat4 | inc_common | matrix for converting from view to world | |
| m_view | highp mat4 | inc_common | matrix for converting from world to view | |
| m_texture | highp mat4 | inc_common | matrix for applying uv orientation | |
| m_normal | mat3 | Not defined | Matrix for vertex normal transformations |
Skinmesh Uniforms
| Uniform | Type | Located In | Compatibility | Purpose and Notes |
|---|---|---|---|---|
| skinmesh | int | inc_common | Equals 1 if the mesh type is a skinmesh | |
vIndex | vec4 | inc_transform | Bone index | |
vWeight | vec4 | inc_transform | Bone weight | |
| m_boneRotations[n] | mediump vec4 | inc_transform | Mobile only | Contains orientations of bones at the current frame for use with Mobile version. n is between 0 and MAX_NUM_BONES (defined by the engine as a default defined property, as of writing it is 64) and you'd usually use nIndex as n as per inc_transform. |
| m_bonePositions[n] | mediump vec4 | inc_transform | Mobile only | Contains positions of bones at the current frame for use with Mobile version. n is between 0 and MAX_NUM_BONES (defined by the engine as a default defined property, as of writing it is 64) and you'd usually use nIndex as n as per inc_transform. |
| m_bones[n] | highp mat4 | inc_transform | Non-Mobile only | Contains matrix transforms for bones (both position and rotation) for use with non-Mobile versions. n is between 0 and MAX_NUM_BONES (defined by the engine as a default defined property, as of writing it is 64) and you'd usually use nIndex as n as per inc_transform. |
Texture and MTR Uniforms
There are up to 11 textures available via. MTR with an additional 5 are for engine use as per below.
By default (although you can change this with new shader files) 0 is diffuse, 1 is normal map, 2 is specular map, 3 is roughness map, 4 is height map and 5 is self illumination map.
11 is FB color, 12 is FB depth, 13 is environment cube, 14 is environment and 15 is noise
| Uniform | Type | Located In | Compatibility | Purpose and Notes |
|---|---|---|---|---|
texture<n>Bound | int | inc_common (for 0 through 5) Else not defined | 11 separate uniforms identifying if texture n is bound, where <n> = 0 to 10. For 11+ see some of the variables below. If it is not 0 it is bound, ie if(texture3Bound != 0) Example name: texture1Bound | |
| texUnit<n> | sampler2D | inc_common (for 0 through 5) Else not defined | 11 separate uniforms containing the texture sampler for texture n, where <n> = 0 to 10 (this is essentially the name of the file) Example name: texUnit5 | |
texFBColorBound | int | Not defined | 1 if the color frame buffer is bound, which it always should be. | |
texFBColor | sampler2D | inc_common | Color Frame Buffer (screen pixel color) (texture slot 11). This buffer is an image with width and height in unit space (0 to 1) as opposed to your screen dimensions. Each fragment contains the pixel color of that pixel on your screen from a previously drawn frame. The color buffer does not contain information from emitter particles. | |
| texFBDepthBound | int | Not defined | 1 if the depth frame buffer is bound, which it always should be. | |
texFBDepth | sampler2D | inc_common | Depth Frame Buffer (texture slot 12). This buffer is an image with width and height in unit space (0 to 1) as opposed to your screen dimensions. Each fragment contains the depth of field at that pixel on your screen from a previously drawn frame. The depth buffer does not contain information from emitter particles. | |
| envMapCube | int | inc_common | Equals 1 if environment map type is cubemap, otherwise type is flatmap | |
texEnvCubeBound | int | inc_common | Bound variable equals 1 if an environment cubemap is bound. | |
texUnitEnvCube | samplerCube | inc_common | Enviroment Cube (texture slot 13). Contains the cubemap sampler for a cubemap environment | |
| texEnvBound | int | inc_common | Equals 1 if an environment flatmap is bound | |
| texUnitEnv | sampler2D | inc_common | contains the texture sampler for the environment map (texture slot 14) | |
| texNoiseBound | int | inc_common | Equals 1 if noise texture was bound | |
| texUnitNoise | sampler2D | inc_common | contains the noise texture sampler (texture slot 15) |
MTR Editable Uniforms
These are not set in the engine but are available in the default game shader files to be edited by the parameter property of MTR files.
| Uniform | Type | Located In | Compatibility | Purpose and Notes |
|---|---|---|---|---|
| DisplacementOffset | float | inc_displacement | Custom MTR edits required | Defines the offset from which height map displacement will begin |
| DisplacementMultiplier | float | inc_displacement | Custom MTR edits required | Multipler of offset |
| Specularity | lowp float | inc_material | Custom MTR edits required | Contains a specularity override value, as passed in from a material file. If not provided, specularity will be imported from texUnit2 red channel, or in the case that specularity is based on the environment map, it will be calculated from there. Positive values only. |
| Roughness | lowp float | inc_material | Custom MTR edits required | Contains a roughness override value, as passed in from a material file. If not provided, roughness will be imported from texUnit3 red channel, or in the case that roughness is also included in the spec map, it will be read from texUnit2 green channel. Positive values only. Use flag MATERIAL_READ_ROUGHNESS_FROM_SPECULAR_MAP = 1 to force reading from texUnit2 green channel. |
| Metallicness | lowp float | inc_material | Custom MTR edits required | Contains a metallicness override value, as passed in from a material file. If not provided, metallicness will be calculated from specularity. Positive values only. |
| CustomSpecularColor | lowp vec4 | inc_material | Custom MTR edits required | Contains a specular color override value, as passed in from a material file. Prevents specular color from being derived from albedo, height, and metallicness. |
| CUSTOM PARAMETER NAME | float int | Not defined | Custom MTR edits required | You can set your own variables in an MTR file that can get picked up by a Shader file. See MTR for details. These can only be float or int. |
PLT Uniforms
| Uniform | Type | Located In | Compatibility | Purpose and Notes |
|---|---|---|---|---|
| PLTscheme[15] | float | fs_pltgen | The PLT color scheme info PLT based diffuse is a composite of a grayscale value from the PLT red channel and a color by number value from the green channel of the PLT, which is passed via texUnit0. The actual color picked is the XY vector equal to RG color vector, and is picked from the gradient map provided in texUnit1. First step is converting the texUnit0 green value through the PLT scheme info, thereby converting it to the proper Y coordinate (gradient row) in texUnit1. |
Light Uniforms
| Uniform | Type | Located In | Compatibility | Purpose and Notes |
|---|---|---|---|---|
vStaticLightDir | vec3 | inc_lightning | Static light direction | |
| numLights | lowp int | inc_lighting | Number of lights passed to the shader for the scene. You have a number of lights between 0 and < numLights to work through where it references n in brackets of other properties. Note there is a #define MAX_NUM_LIGHTS always set which is set by the engine based on the clients Maximum Lights setting (currently 1 up to 128), thus you can do: uniform highp vec4 lightColor [MAX_NUM_LIGHTS]; To get a the maximum array of possible values set, while numLights is dependant on the current players place in the world etc. | |
| lightColor[n] | highp vec4 | inc_lighting | Contains the light color for each light passed to the shader for the scene. Used if gamma correction is enabled. | |
| lightAmbient[n] | highp vec4 | inc_lighting | Contains the ambient light color for each light passed to the shader for the scene. Used if gamma correction is not enabled. | |
| lightDiffuse[n] | highp vec4 | inc_lighting | Contains the diffuse light color for each light passed to the shader for the scene. Used if gamma correction is not enabled. | |
| lightQuadraticAtten[n] | highp float | inc_lighting | Contains the light light falloff calculation for each light in the scene. | |
| lightPosition[n] | highp vec4 | inc_lighting | Contains the position of each light in the scene in world coordinates. | |
| lightFalloffFactor | highp float | inc_lighting | ||
| lightMaxIntensityInv | highp float | inc_lighting | ||
| staticLighting | lowp int | inc_lighting | ||
| lightAreaAmbient | vec3 | inc_lighting | The color of the area ambient lighting at this fragment | |
| lightAreaDiffuse | vec3 | inc_lighting | The color of the area diffuse lighting at this fragment | |
| lightAreaDiffuseDirection | vec3 | inc_lighting | The sun or moon angle for the diffuse light, depending on the time of day. Note: Nwscript function SetAreaLightDirection() in nw_inc_dynlight will only work if the area is set to "Cycle Day and Night" . The uniform will not be updated by the main application if the area flag is set to "Always Bright" or "Always Dark" | |
| materialFrontAmbient | mediump vec4 | inc_lighting | The ambient light color of the fragment based on vertex color | |
| materialFrontDiffuse | mediump vec4 | inc_lighting | The diffuse light color of the fragment based on vertex color | |
| materialFrontEmissive | mediump vec4 | inc_lighting | The self illumination color of the fragment based on the self illumination value of the mesh. Added to total light of that fragment. | |
| frontLightModelProductSceneColor | lowp vec4 | inc_lighting | Used mostly for GUI elements. Used to calculate constant light for those elements. |
Fog Uniforms
| Uniform | Type | Located In | Compatibility | Purpose and Notes |
|---|---|---|---|---|
| fogParams | vec4 | inc_fog vs_beamvol | Contains XYZW = [fogEnabled, fogStart, FogEnd, fogInvEndMinusStart]. Defined as: #define fogEnabled (fogParams.x) #define fogStart (fogParams.y) #define fogEnd (fogParams.z) #define fogInvEndMinusStart (fogParams.w) | |
| fogColor | vec4 | inc_fog inc_postpr_dyn_c fsc_ls fsc_sm fsfblvls | Fog color. NB Fog color is always in gamma space. |
Time Uniforms
| Uniform | Type | Located In | Compatibility | Purpose and Notes |
|---|---|---|---|---|
| sceneCurrentFrame | int | inc_uniforms | Current frame in the renderer UI. Will increment even when paused or on the main menu. | |
worldtimerTimeOfDay (moduleTimeOfDay) | int | inc_uniforms | This value is the number of ticks since the local client was started and does NOT represent anything related to server or module time. There are 144000 ticks per day divided by moduleMinutesPerHour. There is a potential for time error when the module does not load cleanly, causing a large delay. Setting module time with NWScript or debug functions will also not update this value. | |
| moduleYear | int | inc_uniforms | Testing of moduleYear has shown that it does not always get sent to the shader with correct value. Using this value for any purpose can result in counted effects being misrendered. | |
| moduleMonth | int | inc_uniforms | Integer value of module month. Setting module time with NWScript or debug functions will also not update this value correctly. | |
| moduleDay | int | inc_uniforms | Integer value of module day. Setting module time with NWScript or debug functions will also not update this value correctly. | |
| moduleHour | int | inc_uniforms | Integer value of the module time. moduleHour is the integer value of the true* module time. Testing has shown the offset in module hour to be multiple seconds forward or backward, meaning this value cannot be used as an exact match for the true moduleHour. The lower moduleMinutesPerHour is, the larger the error will appear. moduleHour can also become bugged if the module does not load smoothly, causing a large delay. In that case, the module time in game will also be incorrect. Setting module time with NWScript or debug functions will also not update this value correctly. | |
| moduleDawnHour | int | inc_uniforms | The hour at which Dawn-related sky mixing occurs. Sent over to shader from module properties. | |
| moduleDuskHour | int | inc_uniforms | The hour at which Dusk-related sky mixing occurs. Sent over to shader from module properties. | |
| moduleMinutesPerHour | int | inc_uniforms | Time scale of the module. Also directly related to transition timers. Sent over to shader from module properties. | |
| moduleTimeIntoTransition | float | inc_uniforms | This value counts up from the last known transition, such as moduleDuskHour or moduleDawnHour. It also counts up from zero after those transitions end, and so will tick all day long. At these points it resets to 0.0: moduleDawnHour, moduleDawnHour+1, moduleDuskHour, and moduleDuskHour+1. It also starts at 0.0 when the client enters the game, so its initial value is not useful before the first transition it reached. Meaning that if a player starts at 13:24 module time, then the value is worthless as a timer until moduleDuskHour is reached. Otherwise, we can say that the following formula can almost match the module time since the last transition began or ended: float transTimer = moduleTimeIntoTransition / moduleTransitionTime / moduleMinutesPerHour; Beware adding this to moduleHour to correct to the true module time, since moduleHour can tick faster or slower than expected due to server→client information coming out of order. | |
| moduleTransitionTime | float | inc_uniforms | The scale of the transition time. For example, 1 hour is 60 units when moduleMinutesPerHour = 1. moduleTimeIntoTransition / moduleTransitionTime gives a value from 0.0 to 1.0 |
Wind and Weather Uniforms
For Winds the MAX_WINDS variable is currently 32.
| Uniform | Type | Located In | Compatibility | Purpose |
|---|---|---|---|---|
| areaGlobalWind | vec3 | inc_uniforms | Contains the global wind vector for the area | |
| areaWeatherType | int | inc_uniforms | The current weather type. The default ones are defined in the include for ease of use: NWAREA_WEATHER_CLEAR 0 NWAREA_WEATHER_RAIN 1 NWAREA_WEATHER_SNOW 2 These really reference weathertypes.2da noting NWNX can send custom ones. No current way to detect lightning however. | |
| areaWeatherDensity | float | inc_uniforms | Contains the intensity of current weather | |
| windPointSourcesCount | int | inc_uniforms | Number of wind point sources in the scene | |
| windPointSourcesPosition[MAX_WINDS] | vec3 | inc_uniforms | Contains the position of all wind sources in the scene | |
| windPointSourcesRadius[MAX_WINDS] | float | inc_uniforms | Contains the radius of all wind sources in the scene | |
| windPointSourcesDuration[MAX_WINDS] | float | inc_uniforms | Contains the expected duration of each wind source in the scene | |
| windPointSourcesIntensity[MAX_WINDS] | float | inc_uniforms | Contains the wind intensity of each wind source in the scene | |
| windPointSourcesTimeRemaining[MAX_WINDS] | float | inc_uniforms | Contains the remaining time allowed to each wind source in the scene |
Area Uniforms
| Uniform | Type | Located In | Compatibility | Purpose |
|---|---|---|---|---|
| areaFlags | int | inc_uniforms | 1=Interior, 2=Underground, 4=Natural Note with NWNX you can set custom values that are sent to the client. |
Player and Camera Uniforms
| Uniform | Type | Located In | Compatibility | Purpose |
|---|---|---|---|---|
| playerPosition | vec3 | inc_uniforms | player position in world coordinates | |
| playerCameraDist | float | inc_uniforms | distance between player and camera position | |
| playerInCutscene | int | inc_uniforms | flag denoting if player is in cutscene camera mode, 1 is in cutscene mode, 0 is not. | |
| cameraPosition | vec3 | inc_uniforms | position of the camera in world coordinates | |
| cameraOrientation | vec4 | inc_uniforms | camera orientation, a quaternion | |
| cameraFocus | vec3 | inc_uniforms | the vector the camera is focused toward (ie. camera facing) | |
| cameraViewAngle | float | inc_uniforms | ||
| cameraPitch | float | inc_uniforms | ||
| cameraYaw | float | inc_uniforms | ||
| cameraDialogState | int | inc_uniforms | This is the type of camera dialog state. These are the game view of dialog states (or zoom modes) however the player can control it so it is "None" (ie: disable dialogue zoom game option), so it's not indicative of it being in dialog at the time. CAMERA_DIALOG_ZOOM_NONE 0 CAMERA_DIALOG_ZOOM_IN 1 CAMERA_DIALOG_ZOOM_OUT 2 |
User Input Uniforms
| Uniform | Type | Located In | Compatibility | Purpose |
|---|---|---|---|---|
| userinputMousePosition | ivec2 | inc_uniforms | screenspace coordinates of mouse pointer (lower left is 0,0) | |
| userinputMouseButtons | int | inc_uniforms | A mask of mouse buttons currently down: 1 = left, 2 = right, 4 = middle. |
Keyhole Uniforms
| Uniform | Type | Located In | Compatibility | Purpose |
|---|---|---|---|---|
| keyholeCanDissolve | int | inc_keyhole | Equals 1 if keyholing is enabled and the material can be dissolved | |
| keyholeDiameterMax | float | inc_keyhole | Relative to least of resolution width and height. | |
| keyholeDiameterMin | float | inc_keyhole | Relative to least of resolution width and height. | |
| keyholeMinZOffset | inc_keyhole | Offset from position of character below which nothing will be dissolved |
Post Processing Uniforms
While these are generally just shaders being run, the game has various options or console commands that can set these for enabling/disabling/changing the settings a bit.
| Uniform | Type | Located In | Earliest Version | Purpose |
|---|---|---|---|---|
| DOFAmount | float | inc_postpr_dof | Able to be set in console (dof_amount) or by options (graphics.fbo.dof.amount) default 1.0f | |
| DOFDeadZone | float | inc_postpr_dof | Able to be set in console (dof_deafzone) or by options (graphics.fbo.dof.deadzone) default 3.0f | |
| DOFVignette | float | inc_postpr_dof | edge of screen blur. Able to be set in console (dof_vignette) or by options (graphics.fbo.dof.vignette) default 1.0f | |
| DOFFocusType | int | inc_postpr_dof | set to camera pitch (1) by default, set via game option (graphics.fbo.dof.focus-type - "Camera Ptich" = 1, "Dynamic" = 2, "Mouse" = 3, else it will be "Player" = 4) | |
| DOFNeverBlurPC | int | inc_postpr_dof | If 1 then never blurs PC. Default 1. Set via game options (graphics.fbo.dof.never-blur-pc) | |
| DynamicContrastMidpoint | float | inc_postpr_dyn_c | ||
| DynamicContrastIntensity | float | inc_postpr_dyn_c | ||
| Gamma | float | inc_postpr_gam | ||
| Vibrance | float | inc_postpr_vibr | ||
| AORadius | float | not defined | Unused in the SSAO include, but can be set in the console (ssao_radius) default 0.03f | |
| AOIntensity | float | inc_postpr_ssao | Intensity of occlusion. General modifier. (Default: 0.5, settable in console with ssao_intensity) | |
| AOColor | float | not defined | Unused in the SSAO include, but can be set in the console (ssao_color) default 1.0f |
Scriptable Uniforms
| Uniform | Type | Located In | Compatibility | Purpose |
|---|---|---|---|---|
| scriptableInt<n> {1..16} | Int | inc_scriptable | 1.87.8193.35 | A global integer value which can be set per-player via nwscript and passed into all shaders run by that player. The data type appears to be signed integer (Int32), with maximum values of −2,147,483,648 (−231) through 2,147,483,647 (231 − 1) |
| scriptableFloat<n> {1..16} | float | inc_scriptable | A global float value which can be set per-player via nwscript and passed into all shaders run by that player. The data type appears to be signed float (Float32), with expected maximum values of 3.402823466e+38 through 1.175494351e-38 | |
| scriptableVec<n> {1..16} | vec4 | inc_scriptable | A global vec4 value which can be set per-player via nwscript and passed into all shaders run by that player. vec4 can be read in the shader as an array of Float32 values in the order XYZW, or RGBA. Max values are expected to follow Float32 limits as per above. |
Targeting Uniforms
| Uniform | Type | Located In | Compatibility | Purpose |
|---|---|---|---|---|
| targetObjectType | int | inc_target | Identifies the target type of the object under the cursor. Only available in preview build v.87.8193.35[dd1322cd] or later Value corresponds with TARGET_OBJECT_TYPE_* values in NwScript, added in the same build. | |
| targetWorldCoords | vec3 | inc_target | Gives the world coordinates of the cursor. Presumably taken from the projection onto the underlying walkmesh. If no walkmesh exists, will possibly give the position of the skybox under the world, if one goes down that far. Only available in preview build v.87.8193.35[dd1322cd] or later | |
| targetShape | int | inc_target | Identifies the target indicator shape. Only available in preview build v.87.8193.35[dd1322cd] or later Value corresponds with TARGET_SHAPE_* values in NwScript, added in the same build. | |
| targetShapeHarmsEnemies | int | inc_target | Set to 1 if spell using this shape will harm enemies | |
| targetShapeHarmsAllies | int | inc_target | Set to 1 if spell using this shape will harm allies | |
| targetShapeHelpsAllies | int | inc_target | Set to 1 if spell using this shape will help allies | |
| targetShapeIgnoreSelf | int | inc_target | Set to 1 if spell using this shape will ignore the caster | |
| targetShapeOriginOnSelf | int | inc_target | Set to 1 if the spell origin is the caster | |
| targetShapeX | float | inc_target | Specifies the X axis dimensions in meters of the target shape | |
| targetShapeY | float | inc_target | Specifies the Y axis dimensions in meters of the target shape | |
| targetShapeSpellID | int | inc_target | Carries the ID of the spell or spell-like effect which is using this target shape | |
| targetShapeFeatID | int | inc_target | Carries the ID of the feat or feat-like effect which is using this target shape | |
| targetShapeSpellRange | int | inc_target | Specifies the max range of the spell using this target, allowing the shader to draw a dotted line from caster to the point which they need to move to in order to cast the spell to the cursor position. |
Standard Defines Available
| Define | Type | Defined By | Purpose |
|---|---|---|---|
| SHADER_TYPE | int | Engine or MTR file | 1 = Vertex Shader |
| LIGHTING | int | Engine or MTR file | 1 = Will get and perform lighting information in both vertex and fragment shaders |
| KEYHOLING | int | Engine or MTR file | 1 = Will allow keyholing to clip away fragments which could obscure player view |
| FOG | int | Engine or MTR file | 1 = Will get and perform fog application |
| NORMAL_MAP | int | Engine or MTR file | 1 = Expects to find a normal map in material texture1 line Will enable normal map functions |
| SPECULAR_MAP | int | Engine or MTR file | 1 = Expects to find a specular map in material texture2 line Will enable specular map functions |
| ROUGHNESS_MAP | int | Engine or MTR file | 1 = Expects to find a specular map in material texture3 line Will enable roughness map functions |
| HEIGHT_MAP | int | Engine or MTR file | 1 = Expects to find height map in material texture4 line Will enable height map calculations and fragment displacement |
| SELF_ILLUMINATION_MAP | int | Engine or MTR file | 1 = Expects to find illumination map in material texture5 line Will enable self illumination coloring and lighting |
| ENVIRONMENT_MAP | int | Engine or MTR file | 1 = Expects to use an environment map |
| POSITION_WORLD | int | MTR file | 1 = Will calculate world position in the vertex shader and pass that info to the fragment shader Handy information for UV coordinates based on world space Used for water rendering |
| SPECULAR_LIGHT | int | Engine | 1 = This vertex will get specular light. Enables specularity, roughness, and metalicness features |
| FRAGMENT_NORMAL | int | Engine | 1 = Normal will be derived from fragment normal |
| FRAGMENT_LIGHTING | int | Engine | 1 = |
| VERTEX_COLOR | int | Engine | 1 = Vertex color will be passed forward from vertex shader |
| LIGHTING | int | Engine | 1 = Vertex color will come from lighting |
| MATERIAL_READ_SELF_ILLUMINATION_FROM_SPECULAR_MAP | int | MTR | 1 = Will read B&W self-illumination data from specular map (material texture2) blue channel, instead of full color from texture5 |
| SHADER_DEBUG_MODE | int | Engine | Various values equivalent to the shader debug mode options on the in-game debug GUI panel |
| NO_TEXTURE | int | Engine | 1 = if there is no texture map passed to shader |
| NO_TEXTURE_COORDS | int | Engine | 1 = if there is no UV data passed to the shader |
| POSITION_VIEW | int | MTR | 1 = Will calculate position view in the vertex shader and pass that info to the fragment shader |
| GAMMA_CORRECTION | int | Engine | 1 = Will perform gamma correction type based on subtype Also changes how lights are sent to the shader Also changes light attenuation ranges |
| COLOR_CORRECTION_TYPE | int | Engine | 0 = None 1 = Basic color clamp ("Neutral Brightness and Hue Preserve") 2 = ACES color correction |
| POSTPROCESSING | int | Engine | 1 = Means this pass is the post processing pass |
| LIGHT_SUBSURFACE_SCATTERING | int | Engine | |
| LIGHT_SUBSURFACE_SCATTERING_WRAP | int | Engine | |
| SPECULAR_DISTRIBUTION_MODEL | int | Engine | 0 = Blinn-Phong 1 = GGX other = Beckmann |
| SPECULAR_GEOMETRIC_SHADOWING | int | Engine | 2 = Factors in roughness |
| SHADER_QUALITY_MODE | int | Engine | Modifies various shader quality outcomes 0 = Fast Fresnel, no light softening, no roughness shadowing Sets SPECULAR_FRESNEL = 0 1 = Sets SPECULAR_FRESNEL = 2 >1 = Slower Fresnel, extra light fading and mixing, Enables LIGHT_SOFTENING_ENABLED Enables SPECULAR_GEOMETRIC_SHADOWING Sets SPECULAR_FRESNEL = 1 |
| SPECULAR_FRESNEL | int | Engine | 1 = Modifies specular intensity by Fresnel 2 = Mixes Fresnel specularity into specularity |
| LIGHT_SOFTENING_ENABLED | int | Engine | 1 = Smooths light application |
| NO_DISCARD | int | Engine | 1 = Prevents discard calls, forcing 0% alpha to still try drawing on a fragment |
| MATERIAL_ROUGHNESS_OVERRIDE | int | Engine | 1 = Signals shader that roughness value will be in the form of a parameter from the MTR file. Used more explicitly in inc_water. |
| MATERIAL_SPECULARITY_OVRRIDE | int | Engine | 1 = Signals shader that specularity value will be in the form of a parameter from the MTR file. Used more explicitly in inc_water. |
| MATERIAL_METALICNESS_OVERRIDE | int | Engine | 1 = Signals shader that metalicness value will be in the form of a parameter from the MTR file. Used more explicitly in inc_water. |
| MATERIAL_READ_ROUGHNESS_FROM_SPECULAR_MAP | int | MTR | 1 = Will read roughness from texture2 green channel, instead of from texture3 red channel |
| MATERIAL_SPECULAR_COLOR_OVERRIDE | int | Engine | 1 = Changes how specular color is handled. Used more explicitly in inc_water. |
| KEYHOLING_ENABLED | int | Engine | 1 = Similar to KEYHOLING from MTR |
| MOBILE | int | Engine | 1 = User is on a mobile device. Handles differences in how bones and other aspects are handled. |
| POSTPROCESSING_TYPES_ENABLED | int | Engine | Holds the flags for each enabled post processing subroutine that is turned on. |
| MAX_NUM_LIGHTS | int | Engine | Identifies the max number of lights available to the shader lighting loops and the array size of the light data arrays. |
| MAX_NUM_BONES | int | Engine | Identifies how many bones are being sent into the vertex shader for orientation and position calculation of that vertex. |
| BUILD_VERSION | int | Engine | Contains the version number like "8192" |
| BUILD_REVISION | int | Engine | Contains the revision number like "35" |
| FORCE_VERTEX_LIGHTING | int | MTR | 1 = |
Shader Include Files and Hierarchy
The OC shaders have include files which include other include files, not unlike supermodel structure in models and their animations.
As of preview build v.87.8193.35[dd1322cd] custom shaders making use of uniforms copied from inc_water/fs_water will give "redefinition" error #198 in the toolset, such as:
ERROR: 1:4352: error(#198) Redefinition error: moduleMinutesPerHour
To fix that issue, simply remove any line using "uniform <type> <name>" where <name> is defined as a uniform within inc_uniforms
As of preview build v.87.8193.35[2070a8b9] an additional subset of uniforms was moved into inc_uniforms.
Include Files
Include files are essentially similar to nwscript which are pragma_once style includes. For real stability for different client versions (eg supporting versions 35, 36 and 37 all at once) you would have the chain of includes for each version referenced behind a version #IF check, so they load the correct default shaders.
| Filename | Purpose |
|---|---|
| inc_standard | Contains standard shader application functions, as well as debug modes, and input initialization. Works as an include hub, bringing in code from other important includes. |
| inc_lighting | Contains functions for calculating lighting. Also includes the array of lights and their setup. Handles specular and fresnel content. |
| inc_material | Sets up standard material maps 0 to 5. Handles environment mapping, initializes specular mapping, and begins height map displacement. |
| inc_common | Sets up enumerations and constant color values. Makes sure many switches are at least set to 0 rather than null. Contains uniforms related to screenspace, clipping, and projection matrices. Contains functions related to matrix transforms and color correction. |
| inc_config | Short file handling testing switches, such as light softening and specular distribution. |
| inc_keyhole | Setup and use of keyholing. |
| inc_water | Works like inc_standard for fancy water. |
| inc_envmap | Sets up environment maps and cubes. Includes functions for picking from those maps. |
| inc_fog | Handles construction and application of fog. If not included, some important fog uniforms will not be available. |
| inc_transform | Sets up texture-handedness, handles bones for skins, and manages base transforms. When requested, will also setup world, and projection positions for use in fragment shader. |
| inc_uniforms | Contains a bunch of uniforms previously dispersed throughout other files, such as fs_water. |
| inc_random | Contains functions for producing random numbers, noise, and gradients. |
| inc_displacement | Handles height map displacement |
| inc_target | Handles new spell targetning shapes |
| inc_tonemap | Contains a bunch of color correction functions previously found in inc_lighting and others. |
| inc_framebuffer | Sets up framebuffer for color and depth. Includes functions for convering screenspace to worldspace and back again. |
| inc_scriptable | Includes global shader uniforms commandable via nwscript. |
| inc_postpr | The hub entrypoint for postprocessing shader. Will include other post processing related files when enabled in client options. |
Include Heirarchy
The current stable structure is:
| inc_standard | ||||
| ↳ | inc_lighting | |||
| | | ↳ | inc_material | ||
| | | ↳ | inc_common | ||
| | | ↳ | inc_config | ||
| ↳ | inc_keyhole | |||
| ↳ | inc_common |
The current patch structure is:
| inc_standard | ||||
| ↳ | inc_lighting | |||
| | | ↳ | inc_material | ||
| | | ┠ | inc_common | ||
| | | | | ↳ | inc_config | |
| | | ↳ | inc_envmap | ||
| | | ↳ | inc_common | ||
| ┠ | inc_fog * | |||
| | | ↳ | inc_common | ||
| ┠ | inc_transform | |||
| | | ↳ | inc_common | ||
| ┠ | inc_keyhole | |||
| | | ↳ | inc_common | ||
| | | ┠ | inc_uniforms | ||
| | | ↳ | inc_random | ||
| | | ↳ | inc_common | ||
| ┠ | inc_displacement | |||
| | | ↳ | inc_common | ||
| ┠ | inc_target | |||
| | | ↳ | inc_uniforms | ||
| ↳ | inc_tonemap | |||
| ↳ | inc_config |
*Only when #define FOG = 1
The current patch water structure:
| inc_water | ||||
| ┠ | inc_config | |||
| ┠ | inc_uniforms | |||
| ┠ | inc_random | |||
| ┠ | inc_framebuffer | |||
| | | ↳ | inc_common | ||
| ↳ | inc_standard |
Red denotes repeated branch. Blue denotes the first instance of an include within the standard tree structure.
Please note that custom and post processing shaders have other structures, sometimes using these includes out of order.
Archived Lists:
Uniforms
This is pre-36 versions of Uniforms, some useful notes to transfer elsewhere;
* int screenWidth, int screenHeight Viewport size. * float nearClip, float farClip Render clipping cutoff. * int sceneCurrentFrame The current render frame. No guarantees to limits or wrapping behaviour. * int worldtimerTimeOfDay The current time of day as seen from the game world, in milliseconds. This value will pause when the game pauses. (MerricksDad: this value is the number of ticks since the client was started. The value is equal to 1444000 ticks per day divided by the number of moduleMinutesPerHour. The additional value appears to be a multi-hour error value related to the number in moduleMinutesPerHour, ) * int windPointSourcesCount (max: 128) A wind point source is a "explosion" source. You can see this with some spells that bend grass around you. This is the number of wind point sources for the current frame; you need this to walk the following vectors: * float windPointSourcesPosition[windPointSourcesCount*3] A vector of X, Y, Z positions for each windPointSource. * float windPointSourcesRadius[windPointSourcesCount] The radius for each windPointSource. * float windPointSourcesIntensity[windPointSourcesCount] The intensity for each windPointSource. * float windPointSourcesTimeRemaining[windPointSourcesCount] The time remaining for each windPointSource. * int moduleDawnHour The module dawn hour (usually something like 8). * int moduleDuskHour The module dusk hour (usually something like 16). * int moduleMinutesPerHour Minutes per hour. You can use this to calculate the dawn/dusk progression. * vec3 areaGlobalWind The global wind vector for the current area (including magnitude). * int areaWeatherType The weather type: 0 = clear, 1 = rain, 2 = snow. * float areaWeatherDensity The weather density as determined by the engine. * int areaFlags A mask of area flags: 1 = interior, 2 = underground, 4 = natural * int moduleYear (MerricksDad: testing of moduleYear has shown that it does not always get sent to the shader with correct value. Using this value for any purpose can result in counted effects being misrendered.) * int moduleMonth * int moduleDay * int moduleHour The module time as seen by the player. (MerricksDad: moduleHour is the integer value of the true module time. Being converted from a float originally, this value will have loss. Testing has shown the offset in module hour to be multiple seconds forward or backward, meaning this value cannot be used as an exact match for the true moduleHour. The lower moduleMinutesPerHour is, the larger the error will appear.) * float moduleTimeIntoTransition (MerricksDad: This value counts up from the last transition, such as moduleDuskHour or moduleDawnHour. It has a few issues. The first issue is that it resets to 0 at multiple points: moduleDawnHour, moduleDawnHour+1, moduleDuskHour, and moduleDuskHour+1. It also resets to 0 when the client enters the game, so its initial value is not useful before the first transition it reached.) * float moduleTransitionTime This describes the day/dusk/dawn/night transition animations for areas. * ivec2 userinputMousePosition Mouse coordinates. * int userinputMouseButtons A mask of mouse buttons currently down: 1 = left, 2 = right, 4 = middle. * int fogEnabled 1 if fog is enabled. * int fogMode Fog mode (0 = linear, 1 = exp, 2 = exp2). * float fogStart, float fogEnd Fog render distances. * vec4 fogColor The current fog colour. * int numLights The number of dynamic lights currently in the scene. * vec4 globalColor The global/world colour. * vec4 frontLightModelProductSceneColor The scene colour (ambient light). * vec4 materialFrontAmbient * vec4 materialFrontDiffuse * vec4 materialFrontSpecular * vec4 materialFrontEmissive * float materialFrontShininess Material source components. * vec4 lightAmbient * vec4 lightDiffuse * vec4 lightSpecular * vec4 lightPosition * vec4 lightHalfVector * float lightConstantAtten * float lightLinearAtten * float lightQuadraticAtten Light source parameters. * int texUnitXX (where 0 <= XX < 14) * int texUnitEnv * int textureXXBound (where 0 <= XX < 14) Bound textures. * vec4 texCoordOffset0, vec4 texCoordOffset1 * float texCoordRot0, float texCoordRot1 Bound textures position and rotation. * mat4 m_m * mat4 m_mv * mat4 m_mvp Model, ModelView and ModelViewProjection matrices for vertex transformations.
In addition to the uniforms, the following vertex attributes are exposed (NOTE: This is pre-36 and thus will be removed when checked over for any remains to transfer to tables)
sceneCurrentFrame
worldtimerTimeOfDay
windPointSourcesCount
windPointSourcesPosition
windPointSourcesRadius
windPointSourcesIntensity
windPointSourcesTimeRemaining
moduleDawnHour
moduleDuskHour
moduleMinutesPerHour
moduleYear
moduleMonth
moduleDay
moduleHour
moduleTimeIntoTransition
moduleTransitionTime
areaGlobalWind
areaWeatherType
areaWeatherDensity
areaFlags
userinputMousePosition
userinputMouseButtons
m_mvp
m_mv
m_m
m_normal
m_texture
m_view
m_proj
m_vp
m_view_inv
m_proj_inv
m_vp_inv
m_bones[128]
idxmap[128]
lightAmbient[8]
lightDiffuse[8]
lightPosition[8]
lightQuadraticAtten[8]
numLights
FragmentLighting
GammaCorrection
materialFrontAmbient
materialFrontDiffuse
materialFrontSpecular
materialFrontEmissive
materialFrontShininess
frontLightModelProductSceneColor
globalColor
texUnit{0..14}
texUnitEnv
texture{0..15}Bound
fSchemeRow{0..14}
fogEnd
fogMode
fogStart
fogColor
fogEnabled
cameraPitch
cameraYaw
cameraPosition
cameraViewAngle
cameraDialogState
startFadePitch
keyholeCanDissolve
keyholeRadius
nearClip
farClip
screenWidth
screenHeight
AORadius
AOIntensity
AOColor
blackPoint
whitePoint
Vibrance
RGBBalance
DOFAmount
Gamma
playerPosition
playerOrientation
playerInCutscene
playerCameraDist