diff --git a/res/shaders/bonetransform.glsl b/res/shaders/bonetransform.glsl index 5d2af97b..69e4dc7a 100644 --- a/res/shaders/bonetransform.glsl +++ b/res/shaders/bonetransform.glsl @@ -1,8 +1,4 @@ -layout ( location = 5 ) in vec4 boneWeights0; -layout ( location = 6 ) in vec4 boneWeights1; - -uniform int numBones; -uniform mat3x4 boneTransforms[MAX_NUM_BONES]; +layout ( location = 5 ) in float boneWeights[8]; #ifdef BT_POSITION_ONLY void boneTransform( inout vec4 v ) @@ -22,16 +18,10 @@ void boneTransform( inout vec4 v, inout vec3 n, inout vec3 t, inout vec3 b ) #endif float wSum = 0.0; for ( int i = 0; i < 8; i++ ) { - float bw; - if ( i < 4 ) - bw = boneWeights0[i]; - else - bw = boneWeights1[i & 3]; + float bw = boneWeights[i]; if ( !( bw > 0.0 ) ) break; - int bone = int( bw ); - if ( bone >= numBones ) - continue; + int bone = int( bw ) & 0xFF; float w = fract( bw ); mat3x4 m = boneTransforms[bone]; vTmp += v * m * w; diff --git a/res/shaders/default.frag b/res/shaders/default.frag index f120dd9f..58d59ac9 100644 --- a/res/shaders/default.frag +++ b/res/shaders/default.frag @@ -35,6 +35,7 @@ in vec2 texCoords[9]; in vec4 A; in vec4 C; in vec4 D; +in float glowScale; in vec3 N; @@ -79,7 +80,7 @@ void main() vec3 emissive = frontMaterialEmission.rgb * frontMaterialEmission.a; if ( ( vertexColorFlags & 0x10 ) != 0 ) emissive = C.rgb * C.a; - color.rgb += emissive; + color.rgb += emissive * glowScale; color.a *= alpha; @@ -119,7 +120,7 @@ void main() } if ( textures[4].textureUnit > 0 ) { // glow - color.rgb += getTexture( 4 ).rgb; + color.rgb += getTexture( 4 ).rgb * glowScale; } // Specular diff --git a/res/shaders/default.vert b/res/shaders/default.vert index d575f5b1..9fc3a9f0 100644 --- a/res/shaders/default.vert +++ b/res/shaders/default.vert @@ -8,16 +8,14 @@ out vec2 texCoords[9]; out vec4 A; out vec4 C; out vec4 D; +out float glowScale; out vec3 N; -uniform mat3 viewMatrix; -uniform mat3 normalMatrix; +#include "uniforms.glsl" + +uniform mat3 normalMatrix; // in row-major order uniform mat4 modelViewMatrix; -uniform mat4 projectionMatrix; -uniform vec4 lightSourcePosition[3]; // W0 = environment map rotation (-1.0 to 1.0), W1, W2 = viewport X, Y -uniform vec4 lightSourceDiffuse[3]; // A0 = overall brightness, A1, A2 = viewport width, height -uniform vec4 lightSourceAmbient; // A = tone mapping control (1.0 = full tone mapping) uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color @@ -42,7 +40,7 @@ void main() vec4 v = vec4( vertexPosition, 1.0 ); vec3 n = normalVector; - if ( numBones > 0 ) + if ( boneWeights[0] > 0.0 && renderOptions1.x != 0 ) boneTransform( v, n ); v = modelViewMatrix * v; @@ -65,7 +63,8 @@ void main() ViewDir = -v.xyz; LightDir = lightSourcePosition[0].xyz; - A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, lightSourceAmbient.a ); + A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, lightingControls.x ); C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); - D = vec4( sqrt(lightSourceDiffuse[0].rgb), lightSourceDiffuse[0].a ); + D = sqrt( vec4(lightSourceDiffuse[0].rgb, lightingControls.y) ); + glowScale = sqrt( lightingControls.z ); } diff --git a/res/shaders/drawline.glsl b/res/shaders/drawline.glsl index 09e5a151..21b0c746 100644 --- a/res/shaders/drawline.glsl +++ b/res/shaders/drawline.glsl @@ -1,6 +1,3 @@ -uniform vec4 lightSourcePosition[3]; // W0 = environment map rotation (-1.0 to 1.0), W1, W2 = viewport X, Y -uniform vec4 lightSourceDiffuse[3]; // A0 = overall brightness, A1, A2 = viewport width, height - uniform float lineWidth; void drawLine( vec4 p0, vec4 p1 ) @@ -19,8 +16,8 @@ void drawLine( vec4 p0, vec4 p1 ) vec3 p0_ndc = p0.xyz / p0.w; vec3 p1_ndc = p1.xyz / p1.w; - vec2 vpScale = vec2( lightSourceDiffuse[1].a, lightSourceDiffuse[2].a ) * 0.5; - vec2 vpOffs = vec2( lightSourcePosition[1].w, lightSourcePosition[2].w ) + vpScale; + vec2 vpScale = vec2( viewportDimensions.zw ) * 0.5; + vec2 vpOffs = vec2( viewportDimensions.xy ) + vpScale; vec2 p0_ss = p0_ndc.xy * vpScale; vec2 p1_ss = p1_ndc.xy * vpScale; diff --git a/res/shaders/f76_default.frag b/res/shaders/f76_default.frag index f592b15e..903987e4 100644 --- a/res/shaders/f76_default.frag +++ b/res/shaders/f76_default.frag @@ -1,5 +1,7 @@ #version 410 core +#include "uniforms.glsl" + uniform sampler2D BaseMap; uniform sampler2D NormalMap; uniform sampler2D GlowMap; @@ -48,12 +50,10 @@ in vec3 ViewDir; in vec2 texCoord; -in vec4 A; in vec4 C; -in vec4 D; in mat3 btnMatrix; -in mat3 reflMatrix; +flat in mat3 reflMatrix; out vec4 fragColor; @@ -163,13 +163,13 @@ void main() } else if ( hasGlowMap ) { emissive += glowMap.rgb * glowMult; } - emissive *= lightingMap.a; + emissive *= lightingMap.a * lightingControls.z; vec3 f0 = max(reflMap.rgb, vec3(0.02)); // Specular float roughness = 1.0 - lightingMap.r; - vec3 spec = LightingFuncGGX_REF(NdotL0, NdotH, NdotV, max(roughness, 0.02)) * D.rgb; + vec3 spec = LightingFuncGGX_REF(NdotL0, NdotH, NdotV, max(roughness, 0.02)) * lightSourceDiffuse[0].rgb; // Diffuse vec3 diffuse = vec3(NdotL0); @@ -183,7 +183,7 @@ void main() // Environment vec3 refl = vec3(0.0); - vec3 ambient = A.rgb; + vec3 ambient = lightSourceAmbient.rgb; if ( hasCubeMap ) { float m = roughness * (roughness * -4.0 + 10.0); refl = textureLod(CubeMap, reflectedWS, max(m, 0.0)).rgb; @@ -221,7 +221,7 @@ void main() //} // Diffuse - color.rgb = diffuse * albedo * D.rgb; + color.rgb = diffuse * albedo * lightSourceDiffuse[0].rgb; // Ambient color.rgb += ambient * albedo * ao; // Specular @@ -231,7 +231,7 @@ void main() // Emissive color.rgb += emissive; - color.rgb = tonemap(color.rgb * D.a, A.a); + color.rgb = tonemap(color.rgb * lightingControls.y, lightingControls.x); fragColor = color; } diff --git a/res/shaders/f76_default.vert b/res/shaders/f76_default.vert index 8128ee12..9ac4eb94 100644 --- a/res/shaders/f76_default.vert +++ b/res/shaders/f76_default.vert @@ -7,19 +7,14 @@ out vec2 texCoord; out mat3 btnMatrix; -out vec4 A; out vec4 C; -out vec4 D; -out mat3 reflMatrix; +flat out mat3 reflMatrix; -uniform mat3 viewMatrix; -uniform mat3 normalMatrix; +#include "uniforms.glsl" + +uniform mat3 normalMatrix; // in row-major order uniform mat4 modelViewMatrix; -uniform mat4 projectionMatrix; -uniform vec4 lightSourcePosition[3]; // W0 = environment map rotation (-1.0 to 1.0), W1, W2 = viewport X, Y -uniform vec4 lightSourceDiffuse[3]; // A0 = overall brightness, A1, A2 = viewport width, height -uniform vec4 lightSourceAmbient; // A = tone mapping control (1.0 = full tone mapping) uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color @@ -32,15 +27,6 @@ layout ( location = 7 ) in vec2 multiTexCoord0; #include "bonetransform.glsl" -mat3 rotateEnv( mat3 m, float rz ) -{ - float rz_c = cos(rz); - float rz_s = -sin(rz); - return mat3(vec3(m[0][0] * rz_c - m[0][1] * rz_s, m[0][0] * rz_s + m[0][1] * rz_c, m[0][2] * -1.0), - vec3(m[1][0] * rz_c - m[1][1] * rz_s, m[1][0] * rz_s + m[1][1] * rz_c, m[1][2] * -1.0), - vec3(m[2][0] * rz_c - m[2][1] * rz_s, m[2][0] * rz_s + m[2][1] * rz_c, m[2][2] * -1.0)); -} - void main() { vec4 v = vec4( vertexPosition, 1.0 ); @@ -48,7 +34,7 @@ void main() vec3 t = tangentVector; vec3 b = bitangentVector; - if ( numBones > 0 ) + if ( boneWeights[0] > 0.0 && renderOptions1.x != 0 ) boneTransform( v, n, t, b ); v = modelViewMatrix * v; @@ -59,7 +45,10 @@ void main() btnMatrix[1] = normalize( t * normalMatrix ); btnMatrix[0] = normalize( b * normalMatrix ); - reflMatrix = rotateEnv( viewMatrix, lightSourcePosition[0].w * 3.14159265 ); + reflMatrix = envMapRotation; + reflMatrix[0][2] *= -1.0; + reflMatrix[1][2] *= -1.0; + reflMatrix[2][2] *= -1.0; if ( projectionMatrix[3][3] == 1.0 ) ViewDir = vec3(0.0, 0.0, 1.0); // orthographic view @@ -67,7 +56,5 @@ void main() ViewDir = -v.xyz; LightDir = lightSourcePosition[0].xyz; - A = lightSourceAmbient; C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); - D = lightSourceDiffuse[0]; } diff --git a/res/shaders/f76_effectshader.frag b/res/shaders/f76_effectshader.frag index dbc3b662..3e6f0529 100644 --- a/res/shaders/f76_effectshader.frag +++ b/res/shaders/f76_effectshader.frag @@ -1,5 +1,7 @@ #version 410 core +#include "uniforms.glsl" + uniform sampler2D BaseMap; uniform sampler2D GreyscaleMap; uniform samplerCube CubeMap; @@ -46,12 +48,10 @@ in vec3 ViewDir; in vec2 texCoord; -in vec4 A; in vec4 C; -in vec4 D; in mat3 btnMatrix; -in mat3 reflMatrix; +flat in mat3 reflMatrix; out vec4 fragColor; @@ -149,8 +149,8 @@ void main() discard; } - vec3 diffuse = A.rgb + (D.rgb * NdotL); - color.rgb = mix( color.rgb, color.rgb * D.rgb, lightingInfluence ); + vec3 diffuse = lightSourceAmbient.rgb + (lightSourceDiffuse[0].rgb * NdotL); + color.rgb = mix( color.rgb, color.rgb * lightSourceDiffuse[0].rgb, lightingInfluence ); // Specular float g = 1.0; @@ -167,11 +167,11 @@ void main() float m = roughness * (roughness * -4.0 + 10.0); vec3 cube = textureLod( CubeMap, reflectedWS, max(m, 0.0) ).rgb; cube *= envReflection * g; - cube = mix( cube, cube * D.rgb, lightingInfluence ); + cube = mix( cube, cube * lightSourceDiffuse[0].rgb, lightingInfluence ); if ( hasEnvMask ) cube *= texture( EnvironmentMap, offset ).rgb; color.rgb += cube * falloff; } - fragColor = vec4( color.rgb * D.a, color.a ); + fragColor = vec4( color.rgb * lightingControls.y, color.a ); } diff --git a/res/shaders/fo4_default.frag b/res/shaders/fo4_default.frag index 731190f2..79c189eb 100644 --- a/res/shaders/fo4_default.frag +++ b/res/shaders/fo4_default.frag @@ -50,12 +50,13 @@ in vec3 ViewDir; in vec2 texCoord; -in vec4 A; +flat in vec4 A; in vec4 C; -in vec4 D; +flat in vec4 D; +flat in float glowScale; in mat3 btnMatrix; -in mat3 reflMatrix; +flat in mat3 reflMatrix; out vec4 fragColor; @@ -190,7 +191,7 @@ vec3 TorranceSparrow(float NdotL, float NdotH, float NdotV, float VdotH, vec3 co return color * spec * M_PI; } -vec3 tonemap(vec3 x, float y) +vec3 tonemap(vec3 x) { float a = 0.15; float b = 0.50; @@ -199,9 +200,9 @@ vec3 tonemap(vec3 x, float y) float e = 0.02; float f = 0.30; - vec3 z = x * (y * 4.22978723); + vec3 z = x * x * D.a * (A.a * 4.22978723); z = (z * (a * z + b * c) + d * e) / (z * (a * z + b) + d * f) - e / f; - return z / (y * 0.93333333); + return sqrt(z / (A.a * 0.93333333)); } vec4 colorLookup( float x, float y ) { @@ -338,9 +339,9 @@ void main() color.rgb += spec; color.rgb += A.rgb * specMask * fresnelSchlick( VdotH, 0.2 ) * (1.0 - NdotV) * D.rgb; // Emissive - color.rgb += emissive; + color.rgb += emissive * glowScale; - color.rgb = tonemap( color.rgb * D.a, A.a ); + color.rgb = tonemap( color.rgb ); fragColor = color; } diff --git a/res/shaders/fo4_default.vert b/res/shaders/fo4_default.vert index 0ab894e0..f171906d 100644 --- a/res/shaders/fo4_default.vert +++ b/res/shaders/fo4_default.vert @@ -7,19 +7,17 @@ out vec2 texCoord; out mat3 btnMatrix; -out vec4 A; +flat out vec4 A; out vec4 C; -out vec4 D; +flat out vec4 D; +flat out float glowScale; -out mat3 reflMatrix; +flat out mat3 reflMatrix; -uniform mat3 viewMatrix; -uniform mat3 normalMatrix; +#include "uniforms.glsl" + +uniform mat3 normalMatrix; // in row-major order uniform mat4 modelViewMatrix; -uniform mat4 projectionMatrix; -uniform vec4 lightSourcePosition[3]; // W0 = environment map rotation (-1.0 to 1.0), W1, W2 = viewport X, Y -uniform vec4 lightSourceDiffuse[3]; // A0 = overall brightness, A1, A2 = viewport width, height -uniform vec4 lightSourceAmbient; // A = tone mapping control (1.0 = full tone mapping) uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color @@ -39,7 +37,7 @@ void main() vec3 t = tangentVector; vec3 b = bitangentVector; - if ( numBones > 0 ) + if ( boneWeights[0] > 0.0 && renderOptions1.x != 0 ) boneTransform( v, n, t, b ); v = modelViewMatrix * v; @@ -50,9 +48,10 @@ void main() btnMatrix[1] = normalize( t * normalMatrix ); btnMatrix[0] = normalize( b * normalMatrix ); - reflMatrix = mat3( vec3(viewMatrix[0][0], viewMatrix[0][1], viewMatrix[0][2] * -1.0), - vec3(viewMatrix[1][0], viewMatrix[1][1], viewMatrix[1][2] * -1.0), - vec3(viewMatrix[2][0], viewMatrix[2][1], viewMatrix[2][2] * -1.0) ); + reflMatrix = envMapRotation; + reflMatrix[0][2] *= -1.0; + reflMatrix[1][2] *= -1.0; + reflMatrix[2][2] *= -1.0; if ( projectionMatrix[3][3] == 1.0 ) ViewDir = vec3(0.0, 0.0, 1.0); // orthographic view @@ -60,7 +59,8 @@ void main() ViewDir = -v.xyz; LightDir = lightSourcePosition[0].xyz; - A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, lightSourceAmbient.a ); + A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, lightingControls.x ); C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); - D = sqrt( lightSourceDiffuse[0] ); + D = vec4( sqrt(lightSourceDiffuse[0].rgb), lightingControls.y ); + glowScale = sqrt( lightingControls.z ); } diff --git a/res/shaders/fo4_effectshader.frag b/res/shaders/fo4_effectshader.frag index c8eadf46..07dedb57 100644 --- a/res/shaders/fo4_effectshader.frag +++ b/res/shaders/fo4_effectshader.frag @@ -40,12 +40,12 @@ in vec3 ViewDir; in vec2 texCoord; -in vec4 A; +flat in vec4 A; in vec4 C; -in vec4 D; +flat in vec4 D; in mat3 btnMatrix; -in mat3 reflMatrix; +flat in mat3 reflMatrix; out vec4 fragColor; @@ -152,5 +152,5 @@ void main() color.rgb += cube.rgb * falloff; } - fragColor = vec4( color.rgb * D.a, color.a ); + fragColor = vec4( color.rgb * sqrt(D.a), color.a ); } diff --git a/res/shaders/lines.geom b/res/shaders/lines.geom index 481cf31d..1005c9fb 100644 --- a/res/shaders/lines.geom +++ b/res/shaders/lines.geom @@ -3,7 +3,7 @@ layout ( lines ) in; layout ( triangle_strip, max_vertices = 4 ) out; -uniform mat4 projectionMatrix; +#include "uniforms.glsl" in vec4 vsColor[]; out vec4 C; diff --git a/res/shaders/normals.geom b/res/shaders/normals.geom index db0f6fd2..ec5bf48d 100644 --- a/res/shaders/normals.geom +++ b/res/shaders/normals.geom @@ -3,9 +3,10 @@ layout ( points ) in; layout ( triangle_strip, max_vertices = 4 ) out; +#include "uniforms.glsl" + uniform int btnSelection; // 0: draw bitangent, 1: draw tangent, 2: draw normal uniform float normalLineLength; // line length in view space -uniform mat4 projectionMatrix; in mat3 btnMatrix[]; diff --git a/res/shaders/ob_default.frag b/res/shaders/ob_default.frag index f83761f0..f52b3497 100644 --- a/res/shaders/ob_default.frag +++ b/res/shaders/ob_default.frag @@ -52,6 +52,7 @@ in vec2 texCoord; in vec4 A; in vec4 C; in vec4 D; +in float glowScale; out vec4 fragColor; @@ -177,7 +178,7 @@ void main() } // Emissive - vec3 emissive = glowColor.rgb * glowMult; + vec3 emissive = glowColor.rgb * ( glowMult * glowScale ); if ( ( vertexColorFlags & 0x10 ) == 0 ) emissive *= frontMaterialEmission.rgb * frontMaterialEmission.a; else diff --git a/res/shaders/ob_default.vert b/res/shaders/ob_default.vert index 64efc418..240f0c70 100644 --- a/res/shaders/ob_default.vert +++ b/res/shaders/ob_default.vert @@ -8,16 +8,14 @@ out vec2 texCoord; out vec4 A; out vec4 C; out vec4 D; +out float glowScale; out mat3 reflMatrix; -uniform mat3 viewMatrix; -uniform mat3 normalMatrix; +#include "uniforms.glsl" + +uniform mat3 normalMatrix; // in row-major order uniform mat4 modelViewMatrix; -uniform mat4 projectionMatrix; -uniform vec4 lightSourcePosition[3]; // W0 = environment map rotation (-1.0 to 1.0), W1, W2 = viewport X, Y -uniform vec4 lightSourceDiffuse[3]; // A0 = overall brightness, A1, A2 = viewport width, height -uniform vec4 lightSourceAmbient; // A = tone mapping control (1.0 = full tone mapping) uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color @@ -37,7 +35,7 @@ void main() vec3 t = tangentVector; vec3 b = bitangentVector; - if ( numBones > 0 ) + if ( boneWeights[0] > 0.0 && renderOptions1.x != 0 ) boneTransform( v, n, t, b ); v = modelViewMatrix * v; @@ -48,7 +46,7 @@ void main() mat3 btnMatrix = mat3( normalize(b * normalMatrix), normalize(t * normalMatrix), normalize(n * normalMatrix) ); btnMatrix = transpose( btnMatrix ); - reflMatrix = btnMatrix * viewMatrix; + reflMatrix = btnMatrix * envMapRotation; if ( projectionMatrix[3][3] == 1.0 ) ViewDir = btnMatrix * vec3(0.0, 0.0, 1.0); // orthographic view @@ -56,7 +54,8 @@ void main() ViewDir = btnMatrix * -v.xyz; LightDir = btnMatrix * lightSourcePosition[0].xyz; - A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, lightSourceAmbient.a ); + A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, lightingControls.x ); C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); - D = vec4( sqrt(lightSourceDiffuse[0].rgb), lightSourceDiffuse[0].a ); + D = vec4( sqrt(lightSourceDiffuse[0].rgb), lightingControls.y ); + glowScale = sqrt( lightingControls.z ); } diff --git a/res/shaders/particles.geom b/res/shaders/particles.geom index 182f0a1e..bc27b66c 100644 --- a/res/shaders/particles.geom +++ b/res/shaders/particles.geom @@ -5,12 +5,9 @@ layout ( triangle_strip, max_vertices = 4 ) out; uniform vec2 particleScale; -uniform mat4 projectionMatrix; +#include "uniforms.glsl" -in vec4 vsAmbient[]; in vec4 vsColor[]; -in vec4 vsDiffuse[]; - in float vsParticleSize[]; out vec2 texCoords[9]; @@ -18,14 +15,16 @@ out vec2 texCoords[9]; out vec4 A; out vec4 C; out vec4 D; +out float glowScale; out vec3 N; void main() { - A = vsAmbient[0]; + A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, lightingControls.x ); C = vsColor[0]; - D = vsDiffuse[0]; + D = sqrt( vec4(lightSourceDiffuse[0].rgb, lightingControls.y) ); + glowScale = sqrt( lightingControls.z ); N = vec3( 0.0, 0.0, 1.0 ); diff --git a/res/shaders/particles.vert b/res/shaders/particles.vert index ba914d27..91a8b5ae 100644 --- a/res/shaders/particles.vert +++ b/res/shaders/particles.vert @@ -3,17 +3,12 @@ out vec3 LightDir; out vec3 ViewDir; -out vec4 vsAmbient; out vec4 vsColor; -out vec4 vsDiffuse; - out float vsParticleSize; +#include "uniforms.glsl" + uniform mat4 modelViewMatrix; -uniform mat4 projectionMatrix; -uniform vec4 lightSourcePosition[3]; // W0 = environment map rotation (-1.0 to 1.0), W1, W2 = viewport X, Y -uniform vec4 lightSourceDiffuse[3]; // A0 = overall brightness, A1, A2 = viewport width, height -uniform vec4 lightSourceAmbient; // A = tone mapping control (1.0 = full tone mapping) uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color @@ -34,9 +29,6 @@ void main() ViewDir = -v.xyz; LightDir = lightSourcePosition[0].xyz; - vsAmbient = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, lightSourceAmbient.a ); vsColor = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); - vsDiffuse = vec4( sqrt(lightSourceDiffuse[0].rgb), lightSourceDiffuse[0].a ); - vsParticleSize = particleSize; } diff --git a/res/shaders/selection.vert b/res/shaders/selection.vert index d8c7aab8..7b98a34c 100644 --- a/res/shaders/selection.vert +++ b/res/shaders/selection.vert @@ -2,8 +2,9 @@ out vec4 C; +#include "uniforms.glsl" + uniform mat4 modelViewMatrix; -uniform mat4 projectionMatrix; uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color uniform vec4 highlightColor; @@ -27,7 +28,7 @@ void main() { vec4 v = vec4( vertexPosition, 1.0 ); - if ( numBones > 0 ) + if ( boneWeights[0] > 0.0 && renderOptions1.x != 0 ) boneTransform( v ); v = projectionMatrix * ( modelViewMatrix * v ); diff --git a/res/shaders/sk_default.frag b/res/shaders/sk_default.frag index c1362ee7..36e36b62 100644 --- a/res/shaders/sk_default.frag +++ b/res/shaders/sk_default.frag @@ -1,5 +1,7 @@ #version 410 core +#include "uniforms.glsl" + uniform sampler2D BaseMap; uniform sampler2D NormalMap; uniform sampler2D GlowMap; @@ -48,16 +50,16 @@ in vec2 texCoord; in vec4 A; in vec4 C; in vec4 D; +in float glowScale; in mat3 btnMatrix; -in mat3 reflMatrix; out vec4 fragColor; mat3 btnMatrix_norm = mat3(normalize(btnMatrix[0]), normalize(btnMatrix[1]), normalize(btnMatrix[2])); -vec3 tonemap(vec3 x, float y) +vec3 tonemap(vec3 x) { float a = 0.15; float b = 0.50; @@ -66,9 +68,9 @@ vec3 tonemap(vec3 x, float y) float e = 0.02; float f = 0.30; - vec3 z = x * (y * 4.22978723); + vec3 z = x * x * D.a * (A.a * 4.22978723); z = (z * (a * z + b * c) + d * e) / (z * (a * z + b) + d * f) - e / f; - return z / (y * 0.93333333); + return sqrt(z / (A.a * 0.93333333)); } vec3 toGrayscale(vec3 color) @@ -115,7 +117,7 @@ void main() float NdotNegL = max( dot(normal, -L), 0.0 ); vec3 reflected = reflect( -E, normal ); - vec3 reflectedWS = reflMatrix * reflected; + vec3 reflectedWS = envMapRotation * reflected; vec3 albedo = baseMap.rgb * C.rgb; @@ -187,8 +189,8 @@ void main() albedo *= tintColor; } - color.rgb = albedo * (diffuse + emissive) + spec; - color.rgb = tonemap( color.rgb * D.a, A.a ); + color.rgb = albedo * (diffuse + emissive * glowScale) + spec; + color.rgb = tonemap( color.rgb ); fragColor = color; } diff --git a/res/shaders/sk_default.vert b/res/shaders/sk_default.vert index 0e4a06ec..fa32951e 100644 --- a/res/shaders/sk_default.vert +++ b/res/shaders/sk_default.vert @@ -10,16 +10,12 @@ out mat3 btnMatrix; out vec4 A; out vec4 C; out vec4 D; +out float glowScale; -out mat3 reflMatrix; +#include "uniforms.glsl" -uniform mat3 viewMatrix; -uniform mat3 normalMatrix; +uniform mat3 normalMatrix; // in row-major order uniform mat4 modelViewMatrix; -uniform mat4 projectionMatrix; -uniform vec4 lightSourcePosition[3]; // W0 = environment map rotation (-1.0 to 1.0), W1, W2 = viewport X, Y -uniform vec4 lightSourceDiffuse[3]; // A0 = overall brightness, A1, A2 = viewport width, height -uniform vec4 lightSourceAmbient; // A = tone mapping control (1.0 = full tone mapping) uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color @@ -39,7 +35,7 @@ void main() vec3 t = tangentVector; vec3 b = bitangentVector; - if ( numBones > 0 ) + if ( boneWeights[0] > 0.0 && renderOptions1.x != 0 ) boneTransform( v, n, t, b ); v = modelViewMatrix * v; @@ -50,15 +46,14 @@ void main() btnMatrix[1] = normalize( t * normalMatrix ); btnMatrix[0] = normalize( b * normalMatrix ); - reflMatrix = viewMatrix; - if ( projectionMatrix[3][3] == 1.0 ) ViewDir = vec3(0.0, 0.0, 1.0); // orthographic view else ViewDir = -v.xyz; LightDir = lightSourcePosition[0].xyz; - A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, lightSourceAmbient.a ); + A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, lightingControls.x ); C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); - D = sqrt( lightSourceDiffuse[0] ); + D = vec4( sqrt(lightSourceDiffuse[0].rgb), lightingControls.y ); + glowScale = sqrt( lightingControls.z ); } diff --git a/res/shaders/sk_effectshader.vert b/res/shaders/sk_effectshader.vert index 509643e4..92e4afd8 100644 --- a/res/shaders/sk_effectshader.vert +++ b/res/shaders/sk_effectshader.vert @@ -9,12 +9,10 @@ out vec3 N; out vec4 C; -uniform mat3 normalMatrix; +#include "uniforms.glsl" + +uniform mat3 normalMatrix; // in row-major order uniform mat4 modelViewMatrix; -uniform mat4 projectionMatrix; -uniform vec4 lightSourcePosition[3]; // W0 = environment map rotation (-1.0 to 1.0), W1, W2 = viewport X, Y -uniform vec4 lightSourceDiffuse[3]; // A0 = overall brightness, A1, A2 = viewport width, height -uniform vec4 lightSourceAmbient; // A = tone mapping control (1.0 = full tone mapping) uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color @@ -31,7 +29,7 @@ void main() vec4 v = vec4( vertexPosition, 1.0 ); vec3 n = normalVector; - if ( numBones > 0 ) + if ( boneWeights[0] > 0.0 && renderOptions1.x != 0 ) boneTransform( v, n ); v = modelViewMatrix * v; diff --git a/res/shaders/sk_msn.frag b/res/shaders/sk_msn.frag index 82d57e4f..87cc6aa3 100644 --- a/res/shaders/sk_msn.frag +++ b/res/shaders/sk_msn.frag @@ -37,7 +37,7 @@ uniform bool hasTintColor; uniform float lightingEffect1; uniform float lightingEffect2; -uniform mat3 viewMatrix; +uniform mat4 modelViewMatrix; in vec3 LightDir; in vec3 ViewDir; @@ -47,11 +47,12 @@ in vec2 texCoord; in vec4 A; in vec4 C; in vec4 D; +in float glowScale; out vec4 fragColor; -vec3 tonemap(vec3 x, float y) +vec3 tonemap(vec3 x) { float a = 0.15; float b = 0.50; @@ -60,9 +61,9 @@ vec3 tonemap(vec3 x, float y) float e = 0.02; float f = 0.30; - vec3 z = x * (y * 4.22978723); + vec3 z = x * x * D.a * (A.a * 4.22978723); z = (z * (a * z + b * c) + d * e) / (z * (a * z + b) + d * f) - e / f; - return z / (y * 0.93333333); + return sqrt(z / (A.a * 0.93333333)); } vec3 toGrayscale(vec3 color) @@ -109,7 +110,7 @@ void main() // Convert model space to view space // Swizzled G/B values! - normal = normalize( normal.rbg * viewMatrix ); + normal = normalize( mat3(modelViewMatrix) * normal.rbg ); // Face Normals //vec3 X = dFdx(v); @@ -202,8 +203,8 @@ void main() albedo *= tintColor; } - color.rgb = albedo * (diffuse + emissive) + spec; - color.rgb = tonemap( color.rgb * D.a, A.a ); + color.rgb = albedo * (diffuse + emissive * glowScale) + spec; + color.rgb = tonemap( color.rgb ); fragColor = color; } diff --git a/res/shaders/sk_msn.vert b/res/shaders/sk_msn.vert index 5fe38a0c..ffe1ea46 100644 --- a/res/shaders/sk_msn.vert +++ b/res/shaders/sk_msn.vert @@ -8,12 +8,11 @@ out vec2 texCoord; out vec4 A; out vec4 C; out vec4 D; +out float glowScale; + +#include "uniforms.glsl" uniform mat4 modelViewMatrix; -uniform mat4 projectionMatrix; -uniform vec4 lightSourcePosition[3]; // W0 = environment map rotation (-1.0 to 1.0), W1, W2 = viewport X, Y -uniform vec4 lightSourceDiffuse[3]; // A0 = overall brightness, A1, A2 = viewport width, height -uniform vec4 lightSourceAmbient; // A = tone mapping control (1.0 = full tone mapping) uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color @@ -28,7 +27,7 @@ void main() { vec4 v = vec4( vertexPosition, 1.0 ); - if ( numBones > 0 ) + if ( boneWeights[0] > 0.0 && renderOptions1.x != 0 ) boneTransform( v ); v = modelViewMatrix * v; @@ -41,7 +40,8 @@ void main() ViewDir = -v.xyz; LightDir = lightSourcePosition[0].xyz; - A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, lightSourceAmbient.a ); + A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, lightingControls.x ); C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); - D = sqrt( lightSourceDiffuse[0] ); + D = vec4( sqrt(lightSourceDiffuse[0].rgb), lightingControls.y ); + glowScale = sqrt( lightingControls.z ); } diff --git a/res/shaders/sk_multilayer.frag b/res/shaders/sk_multilayer.frag index 661a00c5..3ce684f2 100644 --- a/res/shaders/sk_multilayer.frag +++ b/res/shaders/sk_multilayer.frag @@ -45,6 +45,7 @@ in vec2 texCoord; in vec4 A; in vec4 C; in vec4 D; +in float glowScale; in mat3 btnMatrix; in mat3 reflMatrix; @@ -52,7 +53,7 @@ in mat3 reflMatrix; out vec4 fragColor; -vec3 tonemap(vec3 x, float y) +vec3 tonemap(vec3 x) { float a = 0.15; float b = 0.50; @@ -61,9 +62,9 @@ vec3 tonemap(vec3 x, float y) float e = 0.02; float f = 0.30; - vec3 z = x * (y * 4.22978723); + vec3 z = x * x * D.a * (A.a * 4.22978723); z = (z * (a * z + b * c) + d * e) / (z * (a * z + b) + d * f) - e / f; - return z / (y * 0.93333333); + return sqrt(z / (A.a * 0.93333333)); } vec3 toGrayscale(vec3 color) @@ -221,8 +222,8 @@ void main() emissive += soft * D.rgb; } - color.rgb = albedo * (diffuse + emissive) + spec; - color.rgb = tonemap( color.rgb * D.a, A.a ); + color.rgb = albedo * (diffuse + emissive * glowScale) + spec; + color.rgb = tonemap( color.rgb ); fragColor = color; } diff --git a/res/shaders/skybox.frag b/res/shaders/skybox.frag index 9a3554df..b8a3a9ea 100644 --- a/res/shaders/skybox.frag +++ b/res/shaders/skybox.frag @@ -1,5 +1,7 @@ #version 410 core +#include "uniforms.glsl" + uniform samplerCube CubeMap; uniform bool hasCubeMap; uniform int skyCubeMipLevel; @@ -7,10 +9,7 @@ uniform int skyCubeMipLevel; in vec3 LightDir; in vec3 ViewDir; -in vec4 A; -in vec4 D; - -in mat3 reflMatrix; +flat in mat3 reflMatrix; out vec4 fragColor; @@ -50,17 +49,17 @@ void main() vec3 viewWS = reflMatrix * V; - float m = clamp( float(skyCubeMipLevel), 0.0, 6.0 ); + float m = clamp( float(renderOptions1.z), 0.0, 6.0 ); float roughness = ( 5.0 - sqrt( 25.0 - 4.0 * m ) ) / 4.0; - vec3 color = D.rgb * LightingFuncGGX_REF( VdotL, max(roughness, 0.02) ) * VdotL0; + vec3 color = lightSourceDiffuse[0].rgb * LightingFuncGGX_REF( VdotL, max(roughness, 0.02) ) * VdotL0; // Environment - vec3 ambient = A.rgb; + vec3 ambient = lightSourceAmbient.rgb; if ( hasCubeMap ) { color += textureLod( CubeMap, viewWS, m ).rgb * ambient; } else { color += ambient * 0.08; } - fragColor = vec4( tonemap( color * D.a, A.a ), 0.0 ); + fragColor = vec4( tonemap( color * lightingControls.y, lightingControls.x ), 0.0 ); } diff --git a/res/shaders/skybox.vert b/res/shaders/skybox.vert index 8cbb6747..f27ebef4 100644 --- a/res/shaders/skybox.vert +++ b/res/shaders/skybox.vert @@ -3,43 +3,27 @@ out vec3 LightDir; out vec3 ViewDir; -out vec4 A; -out vec4 D; +flat out mat3 reflMatrix; -out mat3 reflMatrix; +#include "uniforms.glsl" uniform bool invertZAxis; -uniform mat3 viewMatrix; -uniform mat4 modelViewMatrix; -uniform mat4 projectionMatrix; -uniform vec4 lightSourcePosition[3]; // W0 = environment map rotation (-1.0 to 1.0), W1, W2 = viewport X, Y -uniform vec4 lightSourceDiffuse[3]; // A0 = overall brightness, A1, A2 = viewport width, height -uniform vec4 lightSourceAmbient; // A = tone mapping control (1.0 = full tone mapping) - layout ( location = 0 ) in vec3 vertexPosition; -mat3 rotateEnv( mat3 m, float rz ) -{ - float rz_c = cos(rz); - float rz_s = -sin(rz); - float z = ( !invertZAxis ? 1.0 : -1.0 ); - return mat3(vec3(m[0][0] * rz_c - m[0][1] * rz_s, m[0][0] * rz_s + m[0][1] * rz_c, m[0][2] * z), - vec3(m[1][0] * rz_c - m[1][1] * rz_s, m[1][0] * rz_s + m[1][1] * rz_c, m[1][2] * z), - vec3(m[2][0] * rz_c - m[2][1] * rz_s, m[2][0] * rz_s + m[2][1] * rz_c, m[2][2] * z)); -} - void main() { - vec4 v = modelViewMatrix * vec4( vertexPosition, 1.0 ); - - reflMatrix = rotateEnv( viewMatrix, lightSourcePosition[0].w * 3.14159265 ); + vec4 v = vec4( viewMatrix * vertexPosition, 1.0 ); ViewDir = vec3(-v.xy, 1.0); LightDir = lightSourcePosition[0].xyz; - A = lightSourceAmbient; - D = lightSourceDiffuse[0]; + reflMatrix = envMapRotation; + if ( invertZAxis ) { + reflMatrix[0][2] *= -1.0; + reflMatrix[1][2] *= -1.0; + reflMatrix[2][2] *= -1.0; + } if ( projectionMatrix[3][3] == 1.0 ) gl_Position = vec4(0.0, 0.0, 2.0, 1.0); // orthographic view is not supported diff --git a/res/shaders/stf_default.frag b/res/shaders/stf_default.frag index a258e351..0e93e551 100644 --- a/res/shaders/stf_default.frag +++ b/res/shaders/stf_default.frag @@ -204,6 +204,8 @@ struct LayeredMaterial { DetailBlenderSettings detailBlender; }; +#include "uniforms.glsl" + uniform samplerCube CubeMap; uniform samplerCube CubeMap2; uniform bool hasCubeMap; @@ -211,7 +213,6 @@ uniform bool hasSpecular; uniform sampler2D textureUnits[NUM_TEXTURE_UNITS]; -uniform vec4 parallaxOcclusionSettings; // min. steps, max. steps, height scale, height offset // bit 0: alpha testing, bit 1: alpha blending uniform int alphaFlags; @@ -222,12 +223,9 @@ in vec3 ViewDir; in vec4 texCoord; -in vec4 A; in vec4 C; -in vec4 D; in mat3 btnMatrix; -in mat3 reflMatrix; out vec4 fragColor; @@ -245,13 +243,13 @@ float emissiveIntensity( bool useAdaptive, bool adaptiveLimits, vec4 luminancePa float l = luminanceParams[0]; // luminousEmittance if ( useAdaptive ) { - l = dot( A.rgb * 20.0 + D.rgb * 80.0, vec3(0.2126, 0.7152, 0.0722) ); + l = dot( lightSourceAmbient.rgb * 20.0 + lightSourceDiffuse[0].rgb * 80.0, vec3(0.2126, 0.7152, 0.0722) ); l = l * exp2( luminanceParams[1] ); // exposureOffset if ( adaptiveLimits ) // minOffsetEmittance, maxOffsetEmittance l = clamp( l, luminanceParams[3], luminanceParams[2] ); } - return sqrt( l * 0.01 ); + return sqrt( l * 0.01 ) * lightingControls.z; } float LightingFuncGGX_REF( float NdotH, float NdotL, float NdotV, float roughness ) @@ -330,17 +328,17 @@ float getBlenderMask(int n) vec2 parallaxMapping( int n, vec3 V, vec2 offset ) { - if ( parallaxOcclusionSettings.z < 0.0005 ) + if ( renderOptions2.x < 0.0005 ) return offset; // disabled // determine optimal height of each layer - float layerHeight = 1.0 / mix( parallaxOcclusionSettings.y, parallaxOcclusionSettings.x, abs(V.z) ); + float layerHeight = 1.0 / mix( float(renderOptions1.w), 8.0, abs(V.z) ); // current height of the layer float curLayerHeight = 1.0; - vec2 dtex = parallaxOcclusionSettings.z * V.xy / max( abs(V.z), 0.02 ); + vec2 dtex = renderOptions2.x * V.xy / max( abs(V.z), 0.02 ); // current texture coordinates - vec2 currentTextureCoords = offset + ( dtex * parallaxOcclusionSettings.w ); + vec2 currentTextureCoords = offset + ( dtex * renderOptions2.y ); // shift of texture coordinates for each layer dtex *= layerHeight; @@ -621,15 +619,16 @@ void main() float NdotV = abs(dot(normal, V)); float LdotH = dot(L, H); - vec3 reflectedWS = reflMatrix * R; - vec3 normalWS = reflMatrix * normal; + vec3 reflectedWS = envMapRotation * R; + vec3 normalWS = envMapRotation * normal; vec3 f0 = mix(vec3(0.04), baseMap, pbrMap.g); vec3 albedo = baseMap * (1.0 - pbrMap.g); // Specular float roughness = pbrMap.r; - vec3 spec = D.rgb * LightingFuncGGX_REF( NdotH, NdotL0, NdotV, clamp(roughness, 0.045, 0.95) ); + vec3 spec = lightSourceDiffuse[0].rgb; + spec *= LightingFuncGGX_REF( NdotH, NdotL0, NdotV, clamp(roughness, 0.045, 0.95) ); // Diffuse vec3 diffuse = vec3(NdotL0); @@ -643,7 +642,7 @@ void main() // Environment vec3 refl = vec3(0.0); - vec3 ambient = A.rgb; + vec3 ambient = lightSourceAmbient.rgb; if ( hasCubeMap ) { float m = roughness * (roughness * -4.0 + 10.0); refl = textureLod(CubeMap, reflectedWS, max(m, 0.0)).rgb; @@ -668,7 +667,7 @@ void main() refl *= f * envLUT.g; // Diffuse - color.rgb = ( diffuse * D.rgb + ambient ) * albedo * ao; + color.rgb = ( diffuse * lightSourceDiffuse[0].rgb + ambient ) * albedo * ao; // Specular color.rgb += ( spec + refl ) * specOcc; @@ -684,14 +683,14 @@ void main() if ( lm.translucencySettings.isEnabled && lm.translucencySettings.isThin ) { transmissive *= albedo * ( vec3(1.0) - f ) * ao; // TODO: implement flipBackFaceNormalsInViewSpace - color.rgb += transmissive * D.rgb * max( -NdotL, 0.0 ); + color.rgb += transmissive * lightSourceDiffuse[0].rgb * max( -NdotL, 0.0 ); if ( hasCubeMap ) - color.rgb += textureLod( CubeMap2, -normalWS, 0.0 ).rgb * transmissive * A.rgb; + color.rgb += textureLod( CubeMap2, -normalWS, 0.0 ).rgb * transmissive * lightSourceAmbient.rgb; else - color.rgb += transmissive * A.rgb * 0.08; + color.rgb += transmissive * lightSourceAmbient.rgb * 0.08; } - color.rgb = tonemap(color.rgb * D.a, A.a); + color.rgb = tonemap( color.rgb * lightingControls.y, lightingControls.x ); fragColor = color; } diff --git a/res/shaders/stf_default.vert b/res/shaders/stf_default.vert index 1ed377d5..b09a33d9 100644 --- a/res/shaders/stf_default.vert +++ b/res/shaders/stf_default.vert @@ -7,19 +7,12 @@ out vec4 texCoord; out mat3 btnMatrix; -out vec4 A; out vec4 C; -out vec4 D; -out mat3 reflMatrix; +#include "uniforms.glsl" -uniform mat3 viewMatrix; -uniform mat3 normalMatrix; +uniform mat3 normalMatrix; // in row-major order uniform mat4 modelViewMatrix; -uniform mat4 projectionMatrix; -uniform vec4 lightSourcePosition[3]; // W0 = environment map rotation (-1.0 to 1.0), W1, W2 = viewport X, Y -uniform vec4 lightSourceDiffuse[3]; // A0 = overall brightness, A1, A2 = viewport width, height -uniform vec4 lightSourceAmbient; // A = tone mapping control (1.0 = full tone mapping) uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color @@ -31,26 +24,25 @@ layout ( location = 4 ) in vec3 bitangentVector; layout ( location = 7 ) in vec2 multiTexCoord0; layout ( location = 8 ) in vec2 multiTexCoord1; -mat3 rotateEnv( mat3 m, float rz ) -{ - float rz_c = cos(rz); - float rz_s = -sin(rz); - return mat3(vec3(m[0][0] * rz_c - m[0][1] * rz_s, m[0][0] * rz_s + m[0][1] * rz_c, m[0][2]), - vec3(m[1][0] * rz_c - m[1][1] * rz_s, m[1][0] * rz_s + m[1][1] * rz_c, m[1][2]), - vec3(m[2][0] * rz_c - m[2][1] * rz_s, m[2][0] * rz_s + m[2][1] * rz_c, m[2][2])); -} +#include "bonetransform.glsl" void main() { - vec4 v = modelViewMatrix * vec4( vertexPosition, 1.0 ); + vec4 v = vec4( vertexPosition, 1.0 ); + vec3 n = normalVector; + vec3 t = tangentVector; + vec3 b = bitangentVector; + + if ( boneWeights[0] > 0.0 && renderOptions1.x != 0 ) + boneTransform( v, n, t, b ); + + v = modelViewMatrix * v; gl_Position = projectionMatrix * v; texCoord = vec4( multiTexCoord0, multiTexCoord1 ); - btnMatrix[2] = normalize( normalVector * normalMatrix ); - btnMatrix[1] = normalize( tangentVector * normalMatrix ); - btnMatrix[0] = normalize( bitangentVector * normalMatrix ); - - reflMatrix = rotateEnv( viewMatrix, lightSourcePosition[0].w * 3.14159265 ); + btnMatrix[2] = normalize( n * normalMatrix ); + btnMatrix[1] = normalize( t * normalMatrix ); + btnMatrix[0] = normalize( b * normalMatrix ); if ( projectionMatrix[3][3] == 1.0 ) ViewDir = vec3(0.0, 0.0, 1.0); // orthographic view @@ -58,7 +50,5 @@ void main() ViewDir = -v.xyz; LightDir = lightSourcePosition[0].xyz; - A = lightSourceAmbient; C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); - D = lightSourceDiffuse[0]; } diff --git a/res/shaders/wireframe.geom b/res/shaders/wireframe.geom index cd4e6092..269b622e 100644 --- a/res/shaders/wireframe.geom +++ b/res/shaders/wireframe.geom @@ -3,9 +3,7 @@ layout ( triangles ) in; layout ( triangle_strip, max_vertices = 12 ) out; -uniform mat4 projectionMatrix; -uniform vec4 lightSourcePosition[3]; // W0 = environment map rotation (-1.0 to 1.0), W1, W2 = viewport X, Y -uniform vec4 lightSourceDiffuse[3]; // A0 = overall brightness, A1, A2 = viewport width, height +#include "uniforms.glsl" uniform float lineWidth; @@ -28,8 +26,8 @@ void drawLine( vec4 p0, vec4 p1, vec4 p1Color ) vec3 p0_ndc = p0.xyz / p0.w; vec3 p1_ndc = p1.xyz / p1.w; - vec2 vpScale = vec2( lightSourceDiffuse[1].a, lightSourceDiffuse[2].a ) * 0.5; - vec2 vpOffs = vec2( lightSourcePosition[1].w, lightSourcePosition[2].w ) + vpScale; + vec2 vpScale = vec2( viewportDimensions.zw ) * 0.5; + vec2 vpOffs = vec2( viewportDimensions.xy ) + vpScale; vec2 p0_ss = p0_ndc.xy * vpScale; vec2 p1_ss = p1_ndc.xy * vpScale; diff --git a/res/shaders/wireframe.vert b/res/shaders/wireframe.vert index 60c6023a..179902df 100644 --- a/res/shaders/wireframe.vert +++ b/res/shaders/wireframe.vert @@ -4,7 +4,9 @@ out mat3 btnMatrix; out vec4 vsColor; -uniform mat3 normalMatrix; +#include "uniforms.glsl" + +uniform mat3 normalMatrix; // in row-major order uniform mat4 modelViewMatrix; uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color @@ -26,7 +28,7 @@ void main() vec3 t = tangentVector; vec3 b = bitangentVector; - if ( numBones > 0 ) + if ( boneWeights[0] > 0.0 && renderOptions1.x != 0 ) boneTransform( v, n, t, b ); gl_Position = modelViewMatrix * v; diff --git a/src/gl/BSMesh.cpp b/src/gl/BSMesh.cpp index facf9ac0..e12e8b5b 100644 --- a/src/gl/BSMesh.cpp +++ b/src/gl/BSMesh.cpp @@ -17,11 +17,15 @@ BSMesh::BSMesh(Scene* s, const QModelIndex& iBlock) : Shape(s, iBlock) void BSMesh::transformShapes() { - // TODO: implement this -#if 0 if ( isHidden() ) return; -#endif + + if ( !( isSkinned && scene->hasOption(Scene::DoSkinning) ) ) [[likely]] { + transformRigid = true; + return; + } + + updateBoneTransforms(); } void BSMesh::drawShapes( NodeList * secondPass ) @@ -386,6 +390,8 @@ void BSMesh::updateData(const NifModel* nif) resetSkinning(); resetVertexData(); resetSkeletonData(); + skinID = -1; + numWeights = 0; gpuLODs.clear(); boneNames.clear(); @@ -401,6 +407,7 @@ void BSMesh::updateData(const NifModel* nif) lodLevel = std::min(scene->lodLevel, Scene::LodLevel(lodCount - 1)); + const BoneWeightsUNorm * weights = nullptr; auto meshIndex = (hasMeshLODs) ? 0 : lodLevel; if ( lodCount > int(lodLevel) ) { auto& mesh = meshes[meshIndex]; @@ -422,7 +429,11 @@ void BSMesh::updateData(const NifModel* nif) norms = mesh->normals; bitangents = mesh->tangents; mesh->calculateBitangents( tangents ); - weightsUNORM = mesh->weights; + boneWeights0.clear(); + boneWeights1.clear(); + numWeights = int( mesh->weights.size() ); + if ( numWeights >= verts.size() ) + weights = mesh->weights.constData(); gpuLODs = mesh->lods; boundSphere = BoundSphere( verts ); @@ -441,6 +452,7 @@ void BSMesh::updateData(const NifModel* nif) boneData.fill( BoneData(), numBones ); auto iBones = nif->getLinkArray(iSkin, "Bones"); + qsizetype validBones = 0; for ( qsizetype i = 0; i < iBones.size(); i++ ) { auto b = iBones.at( i ); if ( i < numBones ) @@ -449,11 +461,36 @@ void BSMesh::updateData(const NifModel* nif) continue; auto iBone = nif->getBlockIndex(b); boneNames.append(nif->resolveString(iBone, "Name")); + validBones++; } + isSkinned = ( validBones >= numBones ); auto iBoneList = nif->getIndex(iSkinData, "Bone List"); for ( int i = 0; i < numBones; i++ ) boneData[i].setTransform( nif, nif->getIndex( iBoneList, i ) ); + + if ( weights && isSkinned ) { + size_t numVerts = size_t( verts.size() ); + boneWeights0.assign( numVerts, FloatVector4( 0.0f ) ); + for ( size_t i = 0; i < numVerts; i++ ) { + size_t k = 0; + for ( const auto & bw : weights[i].weightsUNORM ) { + unsigned int b = bw.bone; + float w = bw.weight; + if ( b < (unsigned int) numBones && b < 256U && w > ( !b ? 0.00005f : 0.00001f ) ) { + w = float( int(b) ) + ( std::min( w, 1.0f ) * float( 65535.0 / 65536.0 ) ); + if ( k < 4 ) { + boneWeights0[i][k] = w; + } else if ( k < 8 ) { + if ( boneWeights1.size() < numVerts ) [[unlikely]] + boneWeights1.assign( numVerts, FloatVector4( 0.0f ) ); + boneWeights1[i][k & 3] = w; + } + k++; + } + } + } + } } } // Do after dependent blocks above diff --git a/src/gl/BSMesh.h b/src/gl/BSMesh.h index b41f8966..0ad92556 100644 --- a/src/gl/BSMesh.h +++ b/src/gl/BSMesh.h @@ -55,7 +55,7 @@ class BSMesh : public Shape } int skinID = -1; - QVector weightsUNORM; + int numWeights = 0; QVector> gpuLODs; QVector boneNames; diff --git a/src/gl/bsshape.cpp b/src/gl/bsshape.cpp index 41a9115a..3e5747c2 100644 --- a/src/gl/bsshape.cpp +++ b/src/gl/bsshape.cpp @@ -149,8 +149,6 @@ void BSShape::updateData( const NifModel * nif ) resetSkeletonData(); if ( isSkinned && iSkin.isValid() ) { skeletonRoot = nif->getLink( iSkin, "Skeleton Root" ); - if ( nif->getBSVersion() < 130 ) - skeletonTrans = Transform( nif, iSkinData ); bones = nif->getLinkArray( iSkin, "Bones" ); auto nTotalBones = bones.size(); @@ -171,7 +169,7 @@ void BSShape::updateData( const NifModel * nif ) size_t k = 0; for ( int j = 0; j < 4; j++ ) { - if ( bns[j] < nTotalBones && wts[j] > 0.0f ) { + if ( bns[j] < nTotalBones && wts[j] > 0.00001f ) { boneWeights0[i][k] = float( bns[j] ) + ( std::min( wts[j], 1.0f ) * float( 65535.0 / 65536.0 ) ); k++; } diff --git a/src/gl/glcontext.cpp b/src/gl/glcontext.cpp index d24fee60..533c721f 100644 --- a/src/gl/glcontext.cpp +++ b/src/gl/glcontext.cpp @@ -236,7 +236,7 @@ void NifSkopeOpenGLContext::ConditionGroup::addCondition( Condition * c ) } NifSkopeOpenGLContext::Shader::Shader( const std::string_view & n, unsigned int t, GLFunctions * fn ) - : f( fn ), name( n ), id( 0 ), status( false ), isProgram( !t ), maxNumBones( 100 ) + : f( fn ), name( n ), id( 0 ), status( false ), isProgram( !t ) { if ( t ) id = f->glCreateShader( t ); @@ -340,11 +340,10 @@ bool NifSkopeOpenGLContext::Shader::load( const QString & filepath ) { QByteArray data = loadShaderFile( filepath ); - QLatin1StringView macroName( name.ends_with( "vert" ) ? "MAX_NUM_BONES" : "NUM_TEXTURE_UNITS" ); - int macroValue = ( name.ends_with( "vert" ) ? int( maxNumBones ) : TexCache::num_texture_units - 2 ); - qsizetype n = data.indexOf( macroName ); - if ( n >= 0 ) - data.replace( n, macroName.length(), QByteArray::number( macroValue ) ); + if ( name.ends_with( "frag" ) ) { + if ( qsizetype n = data.indexOf( QLatin1StringView("NUM_TEXTURE_UNITS") ); n >= 0 ) + data.replace( n, 17, QByteArray::number( TexCache::num_texture_units - 2 ) ); + } const char * src = data.constData(); @@ -501,6 +500,8 @@ bool NifSkopeOpenGLContext::Program::load( const QString & filepath, NifSkopeOpe id = 0; throw errlog; } + } else if ( unsigned int l = f->glGetUniformBlockIndex( id, "globalUniforms" ); l != GL_INVALID_INDEX ) { + f->glBindBufferBase( GL_UNIFORM_BUFFER, l, context->globalUniformsBufferObject ); } } catch ( QString & x ) @@ -771,10 +772,7 @@ bool NifSkopeOpenGLContext::Program::uniSampler( BSShaderLightingProperty * bspr NifSkopeOpenGLContext::NifSkopeOpenGLContext( QOpenGLContext * context ) - : fn( QOpenGLVersionFunctionsFactory::get< NifSkopeOpenGLContext::GLFunctions >( context ) ), cx( context ), - lightSourcePosition{ FloatVector4( 0.0f, 0.0f, 1.0f, 0.0f ), FloatVector4( 0.0f ), FloatVector4( 0.0f ) }, - lightSourceDiffuse{ FloatVector4( 1.0f ), FloatVector4( 0.0f ), FloatVector4( 0.0f ) }, - lightSourceAmbient( 1.0f ) + : fn( QOpenGLVersionFunctionsFactory::get< NifSkopeOpenGLContext::GLFunctions >( context ) ), cx( context ) { vertexAttrib1f = reinterpret_cast< void (*)( unsigned int, float ) >( cx->getProcAddress( "glVertexAttrib1f" ) ); vertexAttrib2fv = @@ -786,6 +784,18 @@ NifSkopeOpenGLContext::NifSkopeOpenGLContext( QOpenGLContext * context ) if ( !( fn && vertexAttrib1f && vertexAttrib2fv && vertexAttrib3fv && vertexAttrib4fv ) ) throw NifSkopeError( "failed to initialize OpenGL functions" ); rehashShaders(); + + globalUniforms = new GlobalUniforms; + std::memset( &( globalUniforms->viewMatrix[0][0] ), 0, sizeof( GlobalUniforms ) ); + globalUniforms->lightSourcePosition[0][2] = 1.0f; + globalUniforms->lightSourceDiffuse[0] = FloatVector4( 1.0f ); + globalUniforms->lightSourceAmbient = FloatVector4( 1.0f ); + globalUniforms->lightingControls = FloatVector4( 1.0f ); + fn->glGenBuffers( 1, &globalUniformsBufferObject ); + fn->glBindBuffer( GL_UNIFORM_BUFFER, globalUniformsBufferObject ); + fn->glBufferData( GL_UNIFORM_BUFFER, GLsizeiptr( sizeof(FloatVector4) * 768 + sizeof(GlobalUniforms) ), (void *) 0, + GL_DYNAMIC_DRAW ); + fn->glBindBuffer( GL_UNIFORM_BUFFER, 0 ); } NifSkopeOpenGLContext::~NifSkopeOpenGLContext() @@ -801,24 +811,24 @@ NifSkopeOpenGLContext::~NifSkopeOpenGLContext() else delete s; } + fn->glDeleteBuffers( 1, &globalUniformsBufferObject ); + delete globalUniforms; } void NifSkopeOpenGLContext::setViewport( int x, int y, int width, int height ) { - lightSourcePosition[1][3] = float( x ); - lightSourcePosition[2][3] = float( y ); - lightSourceDiffuse[1][3] = float( width ); - lightSourceDiffuse[2][3] = float( height ); + globalUniforms->viewportDimensions[0] = x; + globalUniforms->viewportDimensions[1] = y; + globalUniforms->viewportDimensions[2] = width; + globalUniforms->viewportDimensions[3] = height; fn->glViewport( GLint( x ), GLint( y ), GLsizei( width ), GLsizei( height ) ); } FloatVector4 NifSkopeOpenGLContext::getViewport() const { - if ( lightSourceDiffuse[1][3] > 0.0f ) [[likely]] { - return FloatVector4( lightSourcePosition[1][3], lightSourcePosition[2][3], - lightSourceDiffuse[1][3], lightSourceDiffuse[2][3] ); - } + if ( globalUniforms->viewportDimensions[2] > 0 ) [[likely]] + return FloatVector4::convertInt32( globalUniforms->viewportDimensions ); GLint viewportDims[4]; fn->glGetIntegerv( GL_VIEWPORT, viewportDims ); @@ -901,7 +911,7 @@ void NifSkopeOpenGLContext::rehashShaders() shaderHashMask = m; } -void NifSkopeOpenGLContext::updateShaders( int maxNumBones ) +void NifSkopeOpenGLContext::updateShaders() { releaseShaders(); @@ -925,7 +935,6 @@ void NifSkopeOpenGLContext::updateShaders( int maxNumBones ) if ( !shader ) continue; QString fullPath = dir.filePath( name ); - shader->maxNumBones = std::uint16_t( maxNumBones ); if ( !shader->isProgram ) shader->load( fullPath ); else @@ -978,19 +987,41 @@ void NifSkopeOpenGLContext::stopProgram() fn->glUseProgram( 0 ); } +void NifSkopeOpenGLContext::setViewTransform( const Transform & t, int upAxis, float envMapRotation ) +{ + const float * r = t.rotation.data(); + globalUniforms->viewMatrix[0] = FloatVector4( r[0], r[3], r[6], 0.0f ); + globalUniforms->viewMatrix[1] = FloatVector4( r[1], r[4], r[7], 0.0f ); + globalUniforms->viewMatrix[2] = FloatVector4( r[2], r[5], r[8], 0.0f ); + + FloatVector4 m[3]; + m[0] = FloatVector4::convertVector3( r ); + m[1] = FloatVector4::convertVector3( r + 3 ); + m[2] = FloatVector4::convertVector3( r + 6 ); + if ( upAxis == 0 ) { + m[0].shuffleValues( 0xC9 ); // up axis = X: XYZ -> YZX + m[1].shuffleValues( 0xC9 ); + m[2].shuffleValues( 0xC9 ); + } else if ( upAxis == 1 ) { + m[0].shuffleValues( 0xD2 ); // up axis = Y: XYZ -> ZXY + m[1].shuffleValues( 0xD2 ); + m[2].shuffleValues( 0xD2 ); + } + float r_c = float( std::cos( envMapRotation * float( 3.1415926536 / 180.0 ) ) ); + float r_s = float( std::sin( envMapRotation * float( 3.1415926536 / 180.0 ) ) ); + m[0] = FloatVector4( m[0][0] * r_c - m[0][1] * r_s, m[0][0] * r_s + m[0][1] * r_c, m[0][2], m[0][3] ); + m[1] = FloatVector4( m[1][0] * r_c - m[1][1] * r_s, m[1][0] * r_s + m[1][1] * r_c, m[1][2], m[1][3] ); + m[2] = FloatVector4( m[2][0] * r_c - m[2][1] * r_s, m[2][0] * r_s + m[2][1] * r_c, m[2][2], m[2][3] ); + globalUniforms->envMapRotation[0] = m[0]; + globalUniforms->envMapRotation[1] = m[1]; + globalUniforms->envMapRotation[2] = m[2]; +} + void NifSkopeOpenGLContext::setGlobalUniforms() { - for ( Program * p = programsLinked; p; p = p->nextProgram ) { - fn->glUseProgram( p->id ); - currentProgram = p; - p->uni3m( "viewMatrix", viewMatrix ); - p->uni4m( "projectionMatrix", projectionMatrix ); - p->uni4fv( "lightSourcePosition", lightSourcePosition, 3 ); - p->uni4fv( "lightSourceDiffuse", lightSourceDiffuse, 3 ); - p->uni4f( "lightSourceAmbient", lightSourceAmbient ); - } - currentProgram = nullptr; - fn->glUseProgram( 0 ); + fn->glBindBuffer( GL_UNIFORM_BUFFER, globalUniformsBufferObject ); + fn->glBufferSubData( GL_UNIFORM_BUFFER, 0, GLsizeiptr( sizeof(GlobalUniforms) ), globalUniforms ); + fn->glBindBuffer( GL_UNIFORM_BUFFER, 0 ); } void NifSkopeOpenGLContext::setDefaultVertexAttribs( std::uint64_t attrMask, const float * const * attrData ) @@ -1011,6 +1042,17 @@ void NifSkopeOpenGLContext::setDefaultVertexAttribs( std::uint64_t attrMask, con } } +void NifSkopeOpenGLContext::updateBoneTransforms( const FloatVector4 * boneTransforms, size_t numBones ) +{ + if ( numBones < 1 ) + return; + numBones = std::min< size_t >( numBones, 256 ); + fn->glBindBuffer( GL_UNIFORM_BUFFER, globalUniformsBufferObject ); + fn->glBufferSubData( GL_UNIFORM_BUFFER, GLintptr( sizeof(GlobalUniforms) ), + GLsizeiptr( numBones * sizeof(FloatVector4) * 3 ), boneTransforms ); + fn->glBindBuffer( GL_UNIFORM_BUFFER, 0 ); +} + void NifSkopeOpenGLContext::bindShape( unsigned int numVerts, std::uint64_t attrMask, size_t elementDataSize, const float * const * attrData, const void * elementData ) diff --git a/src/gl/glcontext.hpp b/src/gl/glcontext.hpp index 1ea441fb..b1143352 100644 --- a/src/gl/glcontext.hpp +++ b/src/gl/glcontext.hpp @@ -127,7 +127,6 @@ class NifSkopeOpenGLContext unsigned int id; bool status; bool isProgram; - std::uint16_t maxNumBones; }; public: @@ -281,6 +280,21 @@ class NifSkopeOpenGLContext ~ShapeData(); }; + struct GlobalUniforms { + FloatVector4 viewMatrix[3]; // 3x3 rotation matrix in column-major order + FloatVector4 envMapRotation[3]; // view space to environment map + FloatVector4 projectionMatrix[4]; + FloatVector4 lightSourcePosition[3]; + FloatVector4 lightSourceDiffuse[3]; + FloatVector4 lightSourceAmbient; + // X = tone mapping control (1.0 = full tone mapping), Y = overall brightness, Z = glow scale + FloatVector4 lightingControls; + std::int32_t viewportDimensions[4]; // X, Y, width, height + // skinning enabled, scene flags, cube map background mip level, Starfield POM steps + std::int32_t renderOptions1[4]; + FloatVector4 renderOptions2; // Starfield POM scale, offset + }; + //! Context Functions GLFunctions * fn; //! Context @@ -292,15 +306,8 @@ class NifSkopeOpenGLContext void ( *vertexAttrib3fv )( unsigned int index, const float * v ); void ( *vertexAttrib4fv )( unsigned int index, const float * v ); - //! Global uniforms - Matrix viewMatrix; - Matrix4 projectionMatrix; - // W0 = environment map rotation (-1.0 to 1.0), W1 = viewport X, W2 = viewport Y - FloatVector4 lightSourcePosition[3]; - // A0 = overall brightness, A1 = viewport width, A2 = viewport height - FloatVector4 lightSourceDiffuse[3]; - // A = tone mapping control (1.0 = full tone mapping) - FloatVector4 lightSourceAmbient; + GlobalUniforms * globalUniforms; + unsigned int globalUniformsBufferObject; NifSkopeOpenGLContext( QOpenGLContext * context ); ~NifSkopeOpenGLContext(); @@ -311,7 +318,7 @@ class NifSkopeOpenGLContext FloatVector4 getViewport() const; //! Updates shaders - void updateShaders( int maxNumBones = 100 ); + void updateShaders(); //! Releases shaders void releaseShaders(); //! Select shader program to use @@ -324,8 +331,14 @@ class NifSkopeOpenGLContext return currentProgram; } + void setViewTransform( const Transform & t, int upAxis, float envMapRotation ); + inline void setProjectionMatrix( const Matrix4 & m ) + { + std::memcpy( &( globalUniforms->projectionMatrix[0][0] ), m.data(), sizeof( FloatVector4 ) * 4 ); + } void setGlobalUniforms(); void setDefaultVertexAttribs( std::uint64_t attrMask, const float * const * attrData ); + void updateBoneTransforms( const FloatVector4 * boneTransforms, size_t numBones ); //! Load and bind geometry data without drawing the shape void bindShape( unsigned int numVerts, std::uint64_t attrMask, size_t elementDataSize, diff --git a/src/gl/glmesh.cpp b/src/gl/glmesh.cpp index ba0281fe..44b81ae9 100644 --- a/src/gl/glmesh.cpp +++ b/src/gl/glmesh.cpp @@ -69,11 +69,9 @@ void Mesh::updateImpl( const NifModel * nif, const QModelIndex & index ) void Mesh::addBoneWeight( int vertexNum, int boneNum, float weight ) { - size_t numVerts = size_t( verts.size() ); - if ( !( (unsigned int) vertexNum < numVerts && ( boneNum & ~255 ) == 0 && weight > 0.0f ) ) - return; FloatVector4 * w = boneWeights0.data() + vertexNum; if ( (*w)[3] > 0.0f ) [[unlikely]] { + size_t numVerts = size_t( verts.size() ); if ( boneWeights1.size() < numVerts ) [[unlikely]] boneWeights1.assign( numVerts, FloatVector4( 0.0f ) ); w = boneWeights1.data() + vertexNum; @@ -108,7 +106,6 @@ void Mesh::updateData( const NifModel * nif ) boneWeights0.assign( size_t( numVerts ), FloatVector4( 0.0f ) ); skeletonRoot = nif->getLink( iSkin, "Skeleton Root" ); - skeletonTrans = Transform( nif, iSkinData ); bones = nif->getLinkArray( iSkin, "Bones" ); @@ -126,7 +123,10 @@ void Mesh::updateData( const NifModel * nif ) if ( idxWeights.isValid() ) { for ( int c = 0; c < nif->rowCount( idxWeights ); c++ ) { QModelIndex idx = nif->getIndex( idxWeights, c ); - addBoneWeight( nif->get( idx, "Index" ), b, nif->get( idx, "Weight" ) ); + int i = nif->get( idx, "Index" ); + float w = nif->get( idx, "Weight" ); + if ( (unsigned int) i < (unsigned int) numVerts && b < 256 && w > 0.00001f ) + addBoneWeight( i, b, w ); } } } @@ -136,6 +136,7 @@ void Mesh::updateData( const NifModel * nif ) if ( iSkinPart.isValid() ) { QModelIndex idx = nif->getIndex( iSkinPart, "Partitions" ); + qsizetype numBones = std::min< qsizetype >( bones.size(), 256 ); uint numTris = 0; uint numStrips = 0; for ( int i = 0; i < nif->rowCount( idx ) && idx.isValid(); i++ ) { @@ -151,7 +152,9 @@ void Mesh::updateData( const NifModel * nif ) for ( int w = 0; w < part.numWeightsPerVertex; w++ ) { auto weight = part.weights[v * part.numWeightsPerVertex + w]; - addBoneWeight( vindex, part.boneMap.value( weight.first ), weight.second ); + auto b = part.boneMap.value( weight.first ); + if ( (unsigned int) b < (unsigned int) numBones && weight.second > 0.00001f ) + addBoneWeight( vindex, b, weight.second ); } } } diff --git a/src/gl/glshape.cpp b/src/gl/glshape.cpp index d57ebba6..0e38be4b 100644 --- a/src/gl/glshape.cpp +++ b/src/gl/glshape.cpp @@ -441,7 +441,6 @@ void Shape::resetVertexData() void Shape::resetSkeletonData() { skeletonRoot = 0; - skeletonTrans = Transform(); boneTransforms.clear(); boneWeights0.clear(); @@ -497,28 +496,10 @@ void Shape::setUniforms( NifSkopeOpenGLContext::Program * prog ) const if ( !prog ) [[unlikely]] return; - unsigned int nifVersion = 0; - if ( scene->nifModel ) [[likely]] - nifVersion = scene->nifModel->getBSVersion(); - - size_t numBones = 0; - if ( nifVersion < 170 ) { - // TODO: Starfield skinning is not implemented - if ( !transformRigid ) - numBones = std::min< size_t >( boneTransforms.size() / 3, size_t( prog->maxNumBones ) ); - prog->uni1i( "numBones", int( numBones ) ); - } - - if ( numBones > 0 ) { - if ( int l = prog->uniLocation( "boneTransforms" ); l >= 0 ) - prog->f->glUniformMatrix3x4fv( l, GLsizei( numBones ), GL_FALSE, &( boneTransforms.front()[0] ) ); - } + if ( !transformRigid && !boneTransforms.empty() ) + scene->renderer->updateBoneTransforms( boneTransforms.data(), boneTransforms.size() / 3 ); const Transform & v = viewTrans(); - bool modelSpaceNormals = false; - if ( nifVersion < 130 && prog->name == "sk_msn.prog" ) [[unlikely]] - modelSpaceNormals = true; - prog->uni3m( "viewMatrix", ( !modelSpaceNormals ? scene->view.rotation : v.rotation ) ); prog->uni3m( "normalMatrix", v.rotation ); prog->uni4m( "modelViewMatrix", v.toMatrix4() ); } diff --git a/src/gl/glshape.h b/src/gl/glshape.h index b09abaff..ac1f68ae 100644 --- a/src/gl/glshape.h +++ b/src/gl/glshape.h @@ -139,7 +139,6 @@ class Shape : public Node std::vector boneWeights1; int skeletonRoot = 0; - Transform skeletonTrans; QVector bones; QVector boneData; QVector partitions; diff --git a/src/gl/gltools.cpp b/src/gl/gltools.cpp index 6114c0be..0d0ad4e9 100644 --- a/src/gl/gltools.cpp +++ b/src/gl/gltools.cpp @@ -457,7 +457,6 @@ void Scene::drawPoints( const Vector3 * positions, size_t numVerts ) NifSkopeOpenGLContext * context = renderer; prog->uni4f( "vertexColorOverride", FloatVector4( 1.0e-15f ).maxValues( currentGLColor ) ); prog->uni1i( "selectionParam", -1 ); - prog->uni1i( "numBones", 0 ); float pointSize = currentGLPointSize; if ( selecting ) { @@ -560,7 +559,6 @@ void Scene::drawTriangles( const Vector3 * positions, size_t numVerts, const Flo } prog->uni4m( "modelViewMatrix", *currentModelViewMatrix ); prog->uni1i( "selectionParam", -1 ); - prog->uni1i( "numBones", 0 ); if ( selecting ) { glDisable( GL_BLEND ); @@ -1566,7 +1564,6 @@ NifSkopeOpenGLContext::Program * Scene::setupProgram( std::string_view name, uns prog->uni1f( "lineWidth", currentGLLineWidth ); } else { prog->uni1i( "selectionParam", -1 ); - prog->uni1i( "numBones", 0 ); if ( elementMode == GL_POINTS ) { float pointSize = currentGLPointSize; if ( selecting ) { diff --git a/src/gl/renderer.cpp b/src/gl/renderer.cpp index 70df7ebd..c600111f 100644 --- a/src/gl/renderer.cpp +++ b/src/gl/renderer.cpp @@ -88,12 +88,13 @@ void Renderer::updateSettings() QSettings settings; int tmp = settings.value( "Settings/Render/General/Mesh Cache Size", 128 ).toInt(); - cfg.meshCacheSize = std::uint8_t( std::min< int >( std::max< int >( ( tmp + 4 ) >> 3, 1 ), 128 ) ); + cfg.meshCacheSize = std::uint8_t( std::clamp< int >( ( tmp + 4 ) >> 3, 1, 128 ) ); tmp = settings.value( "Settings/Render/General/Cube Map Bgnd", 1 ).toInt(); - cfg.cubeBgndMipLevel = std::int8_t( std::min< int >( std::max< int >( tmp, -1 ), 6 ) ); - cfg.sfParallaxMaxSteps = short( settings.value( "Settings/Render/General/Sf Parallax Steps", 200 ).toInt() ); - cfg.sfParallaxScale = settings.value( "Settings/Render/General/Sf Parallax Scale", 0.0f).toFloat(); - cfg.sfParallaxOffset = settings.value( "Settings/Render/General/Sf Parallax Offset", 0.5f).toFloat(); + globalUniforms->renderOptions1[2] = std::clamp< int >( tmp, -1, 6 ); + tmp = settings.value( "Settings/Render/General/Sf Parallax Steps", 200 ).toInt(); + globalUniforms->renderOptions1[3] = std::clamp< int >( tmp, 16, 512 ); + globalUniforms->renderOptions2[0] = settings.value( "Settings/Render/General/Sf Parallax Scale", 0.0f).toFloat(); + globalUniforms->renderOptions2[1] = settings.value( "Settings/Render/General/Sf Parallax Offset", 0.5f).toFloat(); cfg.cubeMapPathFO76 = settings.value( "Settings/Render/General/Cube Map Path FO 76", "textures/shared/cubemaps/mipblur_defaultoutside1.dds" ).toString(); cfg.cubeMapPathSTF = settings.value( "Settings/Render/General/Cube Map Path STF", "textures/cubemaps/cell_cityplazacube.dds" ).toString(); setCacheSize( std::uint32_t( cfg.meshCacheSize ) << 23 ); @@ -255,7 +256,6 @@ bool Renderer::setupProgramCE2( const NifModel * nif, Program * prog, Shape * me prog->uni1i( "hasSpecular", int(scene->hasOption(Scene::DoSpecular)) ); prog->uni1i( "lm.shaderModel", mat->shaderModel ); - prog->uni4f( "parallaxOcclusionSettings", FloatVector4( 8.0f, float(cfg.sfParallaxMaxSteps), cfg.sfParallaxScale, cfg.sfParallaxOffset ) ); // emissive settings if ( mat->flags & CE2Material::Flag_LayeredEmissivity && scene->hasOption(Scene::DoGlow) ) { @@ -1334,8 +1334,8 @@ void Renderer::drawSkyBox( Scene * scene ) -10.0f, -10.0f, 10.0f, 10.0f, -10.0f, 10.0f, -10.0f, 10.0f, 10.0f, 10.0f, 10.0f, 10.0f }; - if ( cfg.cubeBgndMipLevel < 0 || !scene->nifModel || scene->nifModel->getBSVersion() < 151 || scene->selecting - || scene->hasVisMode( Scene::VisSilhouette ) ) { + if ( globalUniforms->renderOptions1[2] < 0 || !scene->nifModel || scene->nifModel->getBSVersion() < 151 + || scene->selecting || scene->hasVisMode( Scene::VisSilhouette ) ) { return; } @@ -1372,7 +1372,6 @@ void Renderer::drawSkyBox( Scene * scene ) prog->uni1i( "hasCubeMap", hasCubeMap ); prog->uni1b( "invertZAxis", ( bsVersion < 170 ) ); - prog->uni1i( "skyCubeMipLevel", cfg.cubeBgndMipLevel ); glDisable( GL_BLEND ); glEnable( GL_DEPTH_TEST ); diff --git a/src/gl/renderer.h b/src/gl/renderer.h index 56d7d722..1fa28726 100644 --- a/src/gl/renderer.h +++ b/src/gl/renderer.h @@ -83,10 +83,6 @@ public slots: struct Settings { std::uint8_t meshCacheSize = 16; // in units of 8 MiB - std::int8_t cubeBgndMipLevel = 1; - short sfParallaxMaxSteps = 200; - float sfParallaxScale = 0.0f; - float sfParallaxOffset = 0.5f; QString cubeMapPathFO76; QString cubeMapPathSTF; } cfg; diff --git a/src/glview.cpp b/src/glview.cpp index 5c4a9688..d8aea594 100644 --- a/src/glview.cpp +++ b/src/glview.cpp @@ -398,12 +398,12 @@ void GLView::glProjection( [[maybe_unused]] int x, [[maybe_unused]] int y ) GLdouble h2 = std::tan( ( cfg.fov / Zoom ) / 360 * M_PI ) * nr; GLdouble w2 = h2 * aspect; - scene->renderer->projectionMatrix = Matrix4::fromFrustum( -w2, +w2, -h2, +h2, nr, fr ); + scene->renderer->setProjectionMatrix( Matrix4::fromFrustum( -w2, +w2, -h2, +h2, nr, fr ) ); } else { // Orthographic View GLdouble h2 = Dist / Zoom; GLdouble w2 = h2 * aspect; - scene->renderer->projectionMatrix = Matrix4::fromOrtho( -w2, +w2, -h2, +h2, nr, fr ); + scene->renderer->setProjectionMatrix( Matrix4::fromOrtho( -w2, +w2, -h2, +h2, nr, fr ) ); } } @@ -487,13 +487,16 @@ void GLView::paintGL() // Setup projection mode glProjection(); - FloatVector4 mat_amb( 0.0f, 0.0f, 0.0f, 1.0f ); - FloatVector4 mat_diff( 0.0f, 0.0f, 0.0f, 1.0f ); + cx->globalUniforms->lightingControls = FloatVector4( toneMapping, brightnessScale, 1.0f, 0.0f ); + if ( !scene->hasOption(Scene::DoGlow) ) + cx->globalUniforms->lightingControls[2] = 0.0f; + FloatVector4 mat_amb( 0.0f ); + FloatVector4 mat_diff( 0.0f ); Vector3 lightDir( 0.0f, 0.0f, 1.0f ); bool drawLightPos = false; if ( scene->hasVisMode(Scene::VisSilhouette) ) { - mat_diff[3] = 0.0f; + cx->globalUniforms->lightingControls.blendValues( FloatVector4( 0.0f ), 0x06 ); } else if ( scene->hasOption(Scene::DoLighting) ) { // Setup light @@ -503,12 +506,11 @@ void GLView::paintGL() Matrix m; m.fromEuler( 0, 0, deg2rad( planarAngle ) ); lightDir = m * Vector3( std::sin( decl ), 0.0f, std::cos( decl ) ); - cx->lightSourcePosition[0] = FloatVector4( viewTrans.rotation * lightDir ); + cx->globalUniforms->lightSourcePosition[0] = FloatVector4( viewTrans.rotation * lightDir ); drawLightPos = scene->hasVisMode( Scene::VisLightPos ); } else { - // environment map rotation around the Z axis - cx->lightSourcePosition[0] = FloatVector4( 0.0f, 0.0f, 1.0f, planarAngle / 180.0f ); + cx->globalUniforms->lightSourcePosition[0] = FloatVector4( 0.0f, 0.0f, 1.0f, 0.0f ); } mat_amb = FloatVector4( ambient ); @@ -529,17 +531,19 @@ void GLView::paintGL() c.maxValues( FloatVector4(0.0f) ).minValues( FloatVector4(1.0f) ); c *= brightnessL; mat_diff = c; - mat_diff[3] = brightnessScale; } else { - mat_amb.blendValues( FloatVector4( 0.5f ), 0x07 ); + mat_amb = FloatVector4( 0.5f ); mat_diff = FloatVector4( 1.0f ); + cx->globalUniforms->lightingControls.blendValues( FloatVector4( 1.0f ), 0x03 ); } - cx->viewMatrix = scene->view.rotation; - cx->lightSourceAmbient = mat_amb; - cx->lightSourceDiffuse[0] = mat_diff; - + // in frontal light mode, planar angle controls environment map rotation around the Z axis + cx->setViewTransform( scene->view, int( cfg.upAxis ), ( frontalLight ? planarAngle : 0.0f ) ); + cx->globalUniforms->lightSourceAmbient = mat_amb; + cx->globalUniforms->lightSourceDiffuse[0] = mat_diff; + cx->globalUniforms->renderOptions1[0] = std::int32_t( scene->hasOption(Scene::DoSkinning) ); + cx->globalUniforms->renderOptions1[1] = std::int32_t( scene->options ); cx->setGlobalUniforms(); cx->setDefaultVertexAttribs( Scene::defaultAttrMask, Scene::defaultVertexAttrs ); @@ -607,12 +611,11 @@ void GLView::paintGL() // Square frustum auto nr = 1.0; auto fr = 250.0; - GLdouble h2 = tan( cfg.fov / 360 * M_PI ) * nr; + GLdouble h2 = std::tan( cfg.fov / 360 * M_PI ) * nr; GLdouble w2 = h2; if ( auto prog = scene->useProgram( "lines.prog" ); prog ) { - prog->uni4m( "projectionMatrix", Matrix4::fromFrustum( -w2, +w2, -h2, +h2, nr, fr ) ); - // update viewport dimensions - prog->uni4fv( "lightSourceDiffuse", cx->lightSourceDiffuse, 3 ); + cx->setProjectionMatrix( Matrix4::fromFrustum( -w2, +w2, -h2, +h2, nr, fr ) ); + cx->setGlobalUniforms(); } // Zoom out slightly diff --git a/src/lib/importex/gltf.cpp b/src/lib/importex/gltf.cpp index acf22f7e..1cddf218 100644 --- a/src/lib/importex/gltf.cpp +++ b/src/lib/importex/gltf.cpp @@ -148,7 +148,7 @@ bool exportCreateNodes(const NifModel* nif, const Scene* scene, tinygltf::Model& if ( j ) gltfNode.name += ":LOD" + std::to_string(j); // Skins - if ( mesh->skinID > -1 && mesh->weightsUNORM.size() > 0 ) { + if ( mesh->skinID > -1 && mesh->numWeights > 0 ) { if ( !gltf.skins.values().contains(mesh) ) { gltfSkinID++; } diff --git a/src/ui/widgets/uvedit.cpp b/src/ui/widgets/uvedit.cpp index dd887f3b..097323e5 100644 --- a/src/ui/widgets/uvedit.cpp +++ b/src/ui/widgets/uvedit.cpp @@ -227,7 +227,7 @@ void UVWidget::initializeGL() { cx = new NifSkopeOpenGLContext( context() ); textures->setOpenGLContext( cx ); - cx->updateShaders( 1 ); + cx->updateShaders(); glEnable( GL_MULTISAMPLE ); @@ -462,7 +462,7 @@ void UVWidget::updateViewRect( int width, int height ) double offsY = pos[1] + 0.5 - scaleY * 0.5; viewScaleAndOffset = FloatVector4( float( scaleX ), float( scaleY ), float( offsX ), float( offsY ) ); - cx->projectionMatrix = Matrix4(); + cx->setProjectionMatrix( Matrix4() ); cx->setGlobalUniforms(); cx->setDefaultVertexAttribs( Scene::defaultAttrMask, Scene::defaultVertexAttrs ); @@ -482,12 +482,10 @@ void UVWidget::updateViewRect( int width, int height ) } if ( auto prog = cx->useProgram( "selection.prog" ); prog ) { prog->uni4m( "modelViewMatrix", modelViewMatrix ); - prog->uni1i( "numBones", 0 ); } if ( auto prog = cx->useProgram( "wireframe.prog" ); prog ) { prog->uni3m( "normalMatrix", Matrix() ); prog->uni4m( "modelViewMatrix", modelViewMatrix ); - prog->uni1i( "numBones", 0 ); } }