168 lines
5.4 KiB
Plaintext
168 lines
5.4 KiB
Plaintext
#type vertex
|
|
#version 410 core
|
|
|
|
layout(location = 0) in vec3 v_position;
|
|
layout(location = 1) in vec3 v_normal;
|
|
layout(location = 2) in int v_ao;
|
|
|
|
out vec3 normalWS;
|
|
out vec3 normalVS;
|
|
out vec3 positionVS;
|
|
out vec3 positionWS;
|
|
out vec3 vertexPosition;
|
|
out float ao;
|
|
|
|
uniform mat4 u_worldMatrix;
|
|
uniform mat4 u_viewMatrix;
|
|
|
|
void main()
|
|
{
|
|
vec4 worldPos = u_worldMatrix * vec4(v_position, 1.0);
|
|
gl_Position = u_viewMatrix * worldPos;
|
|
|
|
positionWS = worldPos.xyz;
|
|
positionVS = gl_Position.xyz;
|
|
vertexPosition = v_position;
|
|
|
|
mat3 worldNormalMatrix = transpose(inverse(mat3(u_worldMatrix)));
|
|
normalWS = normalize(worldNormalMatrix * v_normal);
|
|
|
|
mat3 viewNormalMatrix = transpose(inverse(mat3(u_viewMatrix * u_worldMatrix)));
|
|
normalVS = normalize(viewNormalMatrix * v_normal);
|
|
|
|
ao = float(v_ao) / 255;
|
|
}
|
|
|
|
#type fragment
|
|
#version 410 core
|
|
|
|
layout(location = 0) out vec4 fragColor;
|
|
layout(location = 1) out int objectID;
|
|
|
|
in vec3 normalWS;
|
|
in vec3 normalVS;
|
|
in vec3 positionVS;
|
|
in vec3 positionWS;
|
|
in vec3 vertexPosition;
|
|
in float ao;
|
|
|
|
|
|
uniform vec3 u_cameraPos;
|
|
uniform int u_objectID;
|
|
uniform sampler2D u_texture; // Albedo
|
|
uniform sampler2D u_texture_ambient; // Ambient occlusion
|
|
uniform sampler2D u_texture_normal; // Normal map
|
|
uniform sampler2D u_texture_roughness; // Roughness map
|
|
|
|
vec2 getFaceUV(vec3 pos, int face)
|
|
{
|
|
float scaleFactor = 1.2;
|
|
if(face == 0) return vec2(-fract(pos.z / scaleFactor), fract(pos.y / scaleFactor));
|
|
if(face == 1) return vec2(fract(pos.z / scaleFactor), fract(pos.y / scaleFactor));
|
|
if(face == 2) return vec2(fract(pos.x / scaleFactor), -fract(pos.z / scaleFactor));
|
|
if(face == 3) return vec2(fract(pos.x / scaleFactor), fract(pos.z / scaleFactor));
|
|
if(face == 4) return vec2(fract(pos.x / scaleFactor), fract(pos.y / scaleFactor));
|
|
return vec2(-fract(pos.x / scaleFactor), fract(pos.y / scaleFactor));
|
|
}
|
|
|
|
void main()
|
|
{
|
|
vec3 lightDir = normalize(vec3(3, 4, 1));
|
|
|
|
// Cube face weights
|
|
float faceWeights[6];
|
|
faceWeights[0] = clamp(dot(vec3(-1,0,0), normalWS), 0.0, 1.0);
|
|
faceWeights[1] = clamp(dot(vec3(1,0,0), normalWS), 0.0, 1.0);
|
|
faceWeights[2] = clamp(dot(vec3(0,-1,0), normalWS), 0.0, 1.0);
|
|
faceWeights[3] = clamp(dot(vec3(0,1,0), normalWS), 0.0, 1.0);
|
|
faceWeights[4] = clamp(dot(vec3(0,0,-1), normalWS), 0.0, 1.0);
|
|
faceWeights[5] = clamp(dot(vec3(0,0,1), normalWS), 0.0, 1.0);
|
|
|
|
// Soft-hard blend: sharpen dominant face but allow slight interpolation
|
|
float blendSharpness = 8.0; // higher = sharper
|
|
float sumWeights = 0.0;
|
|
for(int i = 0; i < 6; i++) {
|
|
faceWeights[i] = pow(faceWeights[i], blendSharpness);
|
|
sumWeights += faceWeights[i];
|
|
}
|
|
for(int i = 0; i < 6; i++)
|
|
faceWeights[i] /= sumWeights;
|
|
|
|
vec3 bitangents[6] = vec3[6](vec3(0,1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1), vec3(0,1,0), vec3(0,1,0));
|
|
vec3 tangents[6] = vec3[6](vec3(0, 0, -1), vec3(0, 0, 1), vec3(1, 0, 0), vec3(1, 0, 0), vec3(1, 0, 0), vec3(1, 0, 0));
|
|
|
|
vec3 blendedColor = vec3(0.0);
|
|
vec3 blendedNormal = vec3(0.0);
|
|
float blendedAmbient = 0.0;
|
|
float blendedPerceptualRoughness = 0.0;
|
|
|
|
for(int i = 0; i < 6; i++)
|
|
{
|
|
if(faceWeights[i] == 0.0) continue;
|
|
|
|
vec2 uv = getFaceUV(vertexPosition, i);
|
|
|
|
vec3 texColor = texture(u_texture, uv).rgb;
|
|
vec3 texNormal = texture(u_texture_normal, uv).rgb * 2.0 - 1.0;
|
|
float texAmbient = texture(u_texture_ambient, uv).r;
|
|
float texRoughness = texture(u_texture_roughness, uv).r;
|
|
|
|
mat3 TBN = mat3(tangents[i], bitangents[i], normalize(normalWS));
|
|
vec3 worldNormal = normalize(TBN * texNormal);
|
|
|
|
blendedColor += texColor * faceWeights[i];
|
|
blendedNormal += worldNormal * faceWeights[i];
|
|
blendedAmbient += texAmbient * faceWeights[i];
|
|
blendedPerceptualRoughness += texRoughness * faceWeights[i];
|
|
}
|
|
|
|
blendedNormal = normalize(blendedNormal);
|
|
float blendedRoughness = sqrt(blendedPerceptualRoughness);
|
|
|
|
// View direction (camera at origin in view space)
|
|
vec3 viewDir = normalize(-vertexPosition);
|
|
|
|
// Schlick Fresnel
|
|
vec3 F0 = vec3(0.04); // base reflectivity for dielectrics
|
|
float cosTheta = clamp(dot(viewDir, blendedNormal), 0.0, 1.0);
|
|
vec3 fresnel = F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
|
|
|
|
|
vec3 finalColor = blendedAmbient * blendedColor;
|
|
|
|
vec3 N = normalize(blendedNormal);
|
|
vec3 L = normalize(lightDir);
|
|
vec3 V = normalize(u_cameraPos - positionWS);
|
|
|
|
vec3 H = normalize(L + V);
|
|
float roughnessClamped = clamp(1 - blendedRoughness, 0.001, 1.0);
|
|
float specularExponent = (2.0 / (roughnessClamped * roughnessClamped)) - 2.0;
|
|
|
|
float NdotH = max(dot(N, H), 0.0);
|
|
float specular = pow(NdotH, specularExponent);
|
|
|
|
float NdotL = max(dot(N, L), 0.0);
|
|
vec3 diffuse = blendedColor * NdotL * blendedAmbient;
|
|
|
|
blendedAmbient += 0.2;
|
|
vec3 ambient = blendedColor * blendedAmbient;
|
|
float add = clamp(dot(vec3(0, 0, 1), normalize(normalVS)) + 0.2,0, 1) * NdotL;
|
|
finalColor = diffuse + specular * 0.3 + ambient * 0.2 + add;
|
|
|
|
// Add specular
|
|
/*
|
|
finalColor = mix(
|
|
finalColor,
|
|
vec3(0.7, 0.9, 0.3) * NdotL,
|
|
clamp(dot(blendedNormal, vec3(0, 1, 0)) * 10 - 3, 0, 1)
|
|
);*/
|
|
finalColor = mix(
|
|
finalColor,
|
|
vec3(0.8, 0.8, 0.8) * NdotL + vec3(0.3, 0.3, 0.3),
|
|
clamp(dot(blendedNormal, vec3(0, 1, 0)) * 10 - 3, 0, 1)
|
|
);
|
|
|
|
fragColor = vec4(finalColor, 1.0);
|
|
|
|
objectID = u_objectID;
|
|
} |