diff options
| author | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-04-12 17:54:45 -0500 |
|---|---|---|
| committer | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-04-12 17:54:45 -0500 |
| commit | a0355c9b897281d0bfea48bec9d490724ecabd96 (patch) | |
| tree | 42c56ea4f4829a6115f688956858ada3e59fd9ef /libs/preview_nif/data/shaders/sk_effectshader.frag | |
| parent | fa43a71f9d05b3673d42296a80decb2228d68f83 (diff) | |
Add NIF previewer plugin with Linux-specific fixes
Vendored from github.com/Parapets/mo2-preview_nif and adapted for Linux:
- BSA texture resolution via MO2 virtual tree with case-insensitive
fallback walk (Linux FS is case-sensitive; NIFs reference textures
with arbitrary case against files on disk)
- Process-wide cached BSA candidate list, keyed by profile path,
priority-sorted, filtering disabled mods
- Path backslash normalization before loose-file lookup
- Polygon offset on SLSF1_Decal-flagged shapes to break z-ties with
coincident base meshes (road decals, moss overlays)
- Opaque framebuffer via glColorMask alpha lock so alpha-blended shapes
can't bleed the dialog background through the preview area
- QMouseEvent::globalPosition().toPoint() for Qt6 compatibility
Preview dialog behavior (organizercore.cpp):
- Switch previewFile and previewFileWithAlternatives from stack-allocated
exec() to heap + ApplicationModal + show() + WA_DeleteOnClose.
- Parent passed as nullptr so preview lifetime is decoupled from the
stack-allocated ModInfoDialog that spawns it. Nested exec() inside
the enclosing dialog's exec() was softlocking on close.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'libs/preview_nif/data/shaders/sk_effectshader.frag')
| -rw-r--r-- | libs/preview_nif/data/shaders/sk_effectshader.frag | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/libs/preview_nif/data/shaders/sk_effectshader.frag b/libs/preview_nif/data/shaders/sk_effectshader.frag new file mode 100644 index 0000000..3a22388 --- /dev/null +++ b/libs/preview_nif/data/shaders/sk_effectshader.frag @@ -0,0 +1,101 @@ +#version 120 + +uniform sampler2D BaseMap; +uniform sampler2D GreyscaleMap; + +uniform bool doubleSided; + +uniform bool hasSourceTexture; +uniform bool hasGreyscaleMap; +uniform bool greyscaleAlpha; +uniform bool greyscaleColor; + +uniform bool useFalloff; +uniform bool vertexColors; +uniform bool vertexAlpha; + +uniform bool hasWeaponBlood; + +uniform vec4 glowColor; +uniform float glowMult; + +uniform vec2 uvScale; +uniform vec2 uvOffset; + +uniform vec4 falloffParams; +uniform float falloffDepth; + +varying vec2 TexCoord; +varying vec3 LightDir; +varying vec3 ViewDir; + +varying vec4 C; + +varying vec3 N; +varying vec3 v; + +vec4 colorLookup( float x, float y ) { + + return texture2D( GreyscaleMap, vec2( clamp(x, 0.0, 1.0), clamp(y, 0.0, 1.0)) ); +} + +void main( void ) +{ + vec4 baseMap = texture2D( BaseMap, TexCoord.st * uvScale + uvOffset ); + + vec4 color; + + vec3 normal = N; + + // Reconstructed normal + //normal = normalize(cross(dFdy(v.xyz), dFdx(v.xyz))); + + //if ( !doubleSided && !gl_FrontFacing ) { return; } + + vec3 E = normalize(ViewDir); + + float tmp2 = falloffDepth; // Unused right now + + // Falloff + float falloff = 1.0; + if ( useFalloff ) { + float startO = min(falloffParams.z, 1.0); + float stopO = max(falloffParams.w, 0.0); + + // TODO: When X and Y are both 0.0 or both 1.0 the effect is reversed. + falloff = smoothstep( falloffParams.y, falloffParams.x, abs(E.b)); + + falloff = mix( max(falloffParams.w, 0.0), min(falloffParams.z, 1.0), falloff ); + } + + float alphaMult = glowColor.a * glowColor.a; + + color.rgb = baseMap.rgb; + color.a = baseMap.a; + + if ( hasWeaponBlood ) { + color.rgb = vec3( 1.0, 0.0, 0.0 ) * baseMap.r; + color.a = baseMap.a * baseMap.g; + } + + color.rgb *= C.rgb * glowColor.rgb; + color.a *= C.a * falloff * alphaMult; + + if ( greyscaleColor ) { + // Only Red emissive channel is used + float emRGB = glowColor.r; + + vec4 luG = colorLookup( baseMap.g, C.g * falloff * emRGB ); + + color.rgb = luG.rgb; + } + + if ( greyscaleAlpha ) { + vec4 luA = colorLookup( baseMap.a, C.a * falloff * alphaMult ); + + color.a = luA.a; + } + + gl_FragColor.rgb = color.rgb * glowMult; + gl_FragColor.a = color.a; +} |
