175 lines
4.5 KiB
GLSL
175 lines
4.5 KiB
GLSL
#type vertex
|
|
#version 450 core
|
|
|
|
layout(location = 0) in vec3 a_Position;
|
|
layout(location = 1) in vec3 a_Normal;
|
|
layout(location = 2) in vec4 a_Color;
|
|
layout(location = 3) in vec2 a_TexCoords;
|
|
layout(location = 4) in ivec4 a_BoneIDs;
|
|
layout(location = 5) in vec4 a_BoneWeights;
|
|
|
|
// Camera uniform buffer (binding = 0)
|
|
layout(std140, binding = 0) uniform CameraData
|
|
{
|
|
mat4 u_ViewProjection;
|
|
mat4 u_View;
|
|
mat4 u_Projection;
|
|
vec3 u_CameraPosition;
|
|
};
|
|
|
|
// Model uniform buffer (binding = 1)
|
|
layout(std140, binding = 1) uniform ModelData
|
|
{
|
|
mat4 u_Model;
|
|
mat4 u_NormalMatrix;
|
|
int u_ObjectID;
|
|
};
|
|
|
|
// Bone uniform buffer (binding = 4)
|
|
layout(std140, binding = 4) uniform BoneData
|
|
{
|
|
mat4 u_BoneMatrices[128];
|
|
};
|
|
|
|
out vec3 v_WorldPos;
|
|
out vec3 v_Normal;
|
|
out vec2 v_TexCoords;
|
|
flat out int v_ObjectID;
|
|
|
|
void main()
|
|
{
|
|
// Compute skin matrix from bone influences
|
|
mat4 skinMatrix = mat4(0.0);
|
|
for (int i = 0; i < 4; i++) {
|
|
if (a_BoneIDs[i] >= 0) {
|
|
skinMatrix += a_BoneWeights[i] * u_BoneMatrices[a_BoneIDs[i]];
|
|
}
|
|
}
|
|
|
|
// If no bones affect this vertex, use identity
|
|
if (a_BoneWeights[0] == 0.0 && a_BoneWeights[1] == 0.0 &&
|
|
a_BoneWeights[2] == 0.0 && a_BoneWeights[3] == 0.0) {
|
|
skinMatrix = mat4(1.0);
|
|
}
|
|
|
|
vec4 skinnedPos = skinMatrix * vec4(a_Position, 1.0);
|
|
vec4 worldPos = u_Model * skinnedPos;
|
|
v_WorldPos = worldPos.xyz;
|
|
|
|
// Skin the normal
|
|
mat3 skinNormalMatrix = mat3(skinMatrix);
|
|
mat3 normalMatrix = mat3(u_NormalMatrix);
|
|
v_Normal = normalize(normalMatrix * skinNormalMatrix * a_Normal);
|
|
|
|
v_TexCoords = a_TexCoords;
|
|
v_ObjectID = u_ObjectID;
|
|
|
|
gl_Position = u_ViewProjection * worldPos;
|
|
}
|
|
|
|
#type fragment
|
|
#version 450 core
|
|
|
|
layout(location = 0) out vec4 o_Albedo;
|
|
layout(location = 1) out vec4 o_Normal;
|
|
layout(location = 2) out vec4 o_Material;
|
|
layout(location = 3) out vec4 o_Emissive;
|
|
layout(location = 4) out int o_ObjectID;
|
|
|
|
in vec3 v_WorldPos;
|
|
in vec3 v_Normal;
|
|
in vec2 v_TexCoords;
|
|
flat in int v_ObjectID;
|
|
|
|
struct Material
|
|
{
|
|
vec3 albedo;
|
|
float metallic;
|
|
float roughness;
|
|
float ao;
|
|
};
|
|
|
|
uniform Material u_Material;
|
|
|
|
uniform bool u_UseAlbedoMap;
|
|
uniform sampler2D u_AlbedoMap;
|
|
|
|
uniform bool u_UseNormalMap;
|
|
uniform sampler2D u_NormalMap;
|
|
uniform float u_NormalStrength;
|
|
uniform float u_ToksvigStrength;
|
|
|
|
uniform bool u_UseMetallicMap;
|
|
uniform sampler2D u_MetallicMap;
|
|
|
|
uniform bool u_UseRoughnessMap;
|
|
uniform sampler2D u_RoughnessMap;
|
|
|
|
uniform bool u_UseAOMap;
|
|
uniform sampler2D u_AOMap;
|
|
|
|
uniform bool u_FlipUV;
|
|
|
|
vec3 getNormalFromMap(vec2 uv, out float normalVariance, out float normalLength)
|
|
{
|
|
normalVariance = 0.0;
|
|
normalLength = 1.0;
|
|
|
|
if (!u_UseNormalMap)
|
|
return normalize(v_Normal);
|
|
|
|
vec3 tangentNormal = texture(u_NormalMap, uv).xyz * 2.0 - 1.0;
|
|
normalLength = length(tangentNormal);
|
|
|
|
vec3 Q1 = dFdx(v_WorldPos);
|
|
vec3 Q2 = dFdy(v_WorldPos);
|
|
vec2 st1 = dFdx(uv);
|
|
vec2 st2 = dFdy(uv);
|
|
|
|
vec3 N = normalize(v_Normal);
|
|
vec3 T = normalize(Q1 * st2.t - Q2 * st1.t);
|
|
vec3 B = normalize(cross(N, T));
|
|
mat3 TBN = mat3(T, B, N);
|
|
|
|
vec3 worldNormal = normalize(TBN * tangentNormal);
|
|
worldNormal = normalize(mix(N, worldNormal, u_NormalStrength));
|
|
|
|
vec3 dndx = dFdx(worldNormal);
|
|
vec3 dndy = dFdy(worldNormal);
|
|
normalVariance = max(0.0, dot(dndx, dndx) + dot(dndy, dndy));
|
|
return worldNormal;
|
|
}
|
|
|
|
void main()
|
|
{
|
|
vec2 uv = v_TexCoords;
|
|
if (u_FlipUV)
|
|
uv.y = 1.0 - uv.y;
|
|
|
|
vec3 baseColorLinear = pow(u_Material.albedo, vec3(2.2));
|
|
vec3 texColorLinear = u_UseAlbedoMap ? pow(texture(u_AlbedoMap, uv).rgb, vec3(2.2)) : vec3(1.0);
|
|
vec3 albedo = texColorLinear * baseColorLinear;
|
|
|
|
float metallic = u_UseMetallicMap ? texture(u_MetallicMap, uv).r : u_Material.metallic;
|
|
float roughness = u_UseRoughnessMap ? texture(u_RoughnessMap, uv).r : u_Material.roughness;
|
|
float ao = u_UseAOMap ? texture(u_AOMap, uv).r : u_Material.ao;
|
|
|
|
float normalVariance;
|
|
float normalLength;
|
|
vec3 normal = getNormalFromMap(uv, normalVariance, normalLength);
|
|
|
|
float roughnessAA = clamp(roughness, 0.04, 1.0);
|
|
if (u_UseNormalMap)
|
|
{
|
|
float kernelRoughness = min(2.0 * normalVariance, 1.0);
|
|
float tokvsig = clamp(1.0 - normalLength, 0.0, 1.0);
|
|
roughnessAA = clamp(sqrt(roughnessAA * roughnessAA + kernelRoughness + tokvsig * 0.5 * u_ToksvigStrength), 0.04, 1.0);
|
|
}
|
|
|
|
o_Albedo = vec4(albedo, 1.0);
|
|
o_Normal = vec4(normalize(normal), 1.0);
|
|
o_Material = vec4(roughnessAA, metallic, ao, 1.0);
|
|
o_Emissive = vec4(0.0, 0.0, 0.0, 1.0);
|
|
o_ObjectID = v_ObjectID;
|
|
}
|