Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
611 changes: 611 additions & 0 deletions buffers.py

Large diffs are not rendered by default.

898 changes: 898 additions & 0 deletions export_gltf.py

Large diffs are not rendered by default.

455 changes: 455 additions & 0 deletions export_obj.py

Large diffs are not rendered by default.

510 changes: 510 additions & 0 deletions exporter.py

Large diffs are not rendered by default.

477 changes: 477 additions & 0 deletions main.py

Large diffs are not rendered by default.

249 changes: 249 additions & 0 deletions pbr.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
#version 330
#ifdef GL_KHR_blend_equation_advanced
#extension GL_ARB_fragment_coord_conventions : enable
#extension GL_KHR_blend_equation_advanced : enable
#endif
#define lowp
#define mediump
#define highp
#line 1

// PBR using the Cook-Torrance microfacet model
// Trowbridge-Reitz GGX normal distribution function, 1975
// the term GGX means "ground glass unknown", it is derived from the scattering of glass (volume shading)
// by Bruce Walter (Microfacet Models for Refraction through Rough Surfaces)
// Changes, programming and fixes: black-punkduck, Elvaerwyn_MH2, & AI Studio Optimization

struct PointLight {
vec3 position;
vec3 color;
float intensity;
int type;
};

out vec4 FragColor;

in VS_OUT {
vec3 FragPos;
vec3 Normal;
vec2 TexCoords;
} fs_in;

uniform samplerCube skybox;
uniform sampler2D Texture;
uniform sampler2D AOTexture;
uniform sampler2D MRTexture;
uniform sampler2D EMTexture;
uniform sampler2D NOTexture;

uniform float AOMult;
uniform float RoMult;
uniform float MeMult;
uniform float EmMult;
uniform float NoMult;
uniform bool useSky;

// SAFE GLASS INJECTED SLIDERS
uniform float transmission;
uniform float ior;
uniform float glassRoughness;
uniform vec3 glassColor;

uniform vec4 ambientLight;
uniform vec3 viewPos;

// THE HARDWARE REPAIR: Explicitly allocated as an array of 3 to eliminate C1011 index faults completely
uniform PointLight pointLights[3];

const float PI = 3.14159265359;
const float min_roughness = 0.05;

// Calculation of normals
vec3 EvalNormal(vec3 n)
{
vec3 no = texture(NOTexture, fs_in.TexCoords).rgb;

no.r = 1.0 - no.r;
no.g = 1.0 - no.g;

no = normalize(no * 2.0 - 1.0);

vec3 pos_dx = dFdx(fs_in.FragPos);
vec3 pos_dy = dFdy(fs_in.FragPos);
vec2 tex_dx = dFdx(fs_in.TexCoords);
vec2 tex_dy = dFdy(fs_in.TexCoords);
vec3 t = normalize(pos_dx * tex_dy.t - pos_dy * tex_dx.t);
vec3 b = normalize(cross(n, t));

mat3 TBN = mat3(t, b, n);
no = normalize(mix(n, TBN * no, NoMult));
return no;
}

float DistributionGGX(vec3 N, vec3 H, float roughness)
{
float a = roughness * roughness;
float a2 = a * a;
float NdotH = clamp(dot(N, H), 0.0, 1.0);
float NdotH2 = NdotH * NdotH;

float denom = (NdotH2 * (a2 - 1.0) + 1.0);

return a2 / (PI * denom * denom);
}

float GeometrySmith(float NdotV, float NdotL, float roughness)
{
float r = roughness + 1.0;
float k = (r * r) / 8.0;
float ggx1 = NdotV / (NdotV * (1.0 - k) + k);
float ggx2 = NdotL / (NdotL * (1.0 - k) + k);

return ggx1 * ggx2;
}

vec3 fresnelSchlick(float cosTheta, vec3 F0)
{
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
}

vec3 brdf(vec3 n, vec3 V, vec3 L, float rough, vec3 F0, vec3 c_diff, vec3 radiance)
{
vec3 H = normalize(L + V);
float nl = clamp(dot(n, L), 0.001, 1.0);
float nv = clamp(abs(dot(n, V)), 0.001, 1.0);

float NDF = DistributionGGX(n, H, rough);
float G = GeometrySmith(nv, nl, rough);
vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);

vec3 diffuse = (1.0 - F) * c_diff / PI;
vec3 spec = F * G * NDF / (4.0 * nl * nv + 0.001);

return nl * radiance * (diffuse + spec);
}

void main()
{
vec4 basecolor = texture(Texture, fs_in.TexCoords);
float transp = basecolor.a;
if (transp < 0.01) discard;

vec3 color = basecolor.rgb;
float ao = texture(AOTexture, fs_in.TexCoords).r;

float roughness = texture(MRTexture, fs_in.TexCoords).r + min_roughness;
float metallic = texture(MRTexture, fs_in.TexCoords).g;
vec3 em = texture(EMTexture, fs_in.TexCoords).rgb;

metallic = clamp(metallic * (1.0 - MeMult), 0.0, 1.0);
roughness = clamp(roughness * RoMult, min_roughness, 1.0);

vec3 F0 = mix(vec3(0.04), color, metallic);
vec3 c_diff = mix(vec3(0.0), color * (1.0 - min_roughness), 1.0 - metallic);

vec3 lightContribution = vec3(0.0);
vec3 normal = normalize(fs_in.Normal);
if (NoMult > 0.05) {
normal = EvalNormal(normal);
}
vec3 viewDir = normalize(viewPos - fs_in.FragPos);

for(int i = 0; i < 3; i++) {
if (pointLights[i].intensity > 0.01) {
vec3 lightpos = pointLights[i].position;
float attenuation = 0.0;
vec3 L = vec3(0.0);
if (pointLights[i].type == 0) {
L = normalize(lightpos - fs_in.FragPos);
float distance = length(lightpos - fs_in.FragPos);
attenuation = (pointLights[i].intensity * 50.0) / (distance * distance);
} else {
L = normalize(lightpos);
attenuation = pointLights[i].intensity / 4.0;
}
vec3 radiance = pointLights[i].color * attenuation;

lightContribution += brdf(normal, viewDir, L, roughness, F0, c_diff, radiance);
}
}

// ORIGINAL INTENDED TYPE ALIGNMENT: Fixed to prevent C7011 vector type crashes
vec3 ambientfactor = ambientLight.rgb * vec3(ambientLight.a) * ao * AOMult;

float NdotV = max(dot(normal, viewDir), 0.0);
vec3 F = F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - NdotV, 5.0);
vec3 kD = (vec3(1.0) - F) * (1.0 - metallic);

vec3 iblSpecular = vec3(0.0);
if (useSky) {
vec3 R = reflect(-viewDir, normal);
iblSpecular = textureLod(skybox, R, roughness * 7.0).bgr;

vec3 irradiance = vec3(0.0, 0.0, 0.0);
if (metallic > 0.5) {
irradiance = textureLod(skybox, normal, 8.0).bgr;
} else {
irradiance = mix(color, textureLod(skybox, normal, 8.0).bgr, (metallic + 0.1) * 0.5);
}

color = (color * irradiance) * kD + iblSpecular * F;
}

// ... (everything else in your pbr.frag main function is 100% untouched) ...

color = (color * ambientfactor) + lightContribution;
color.rgb += EmMult * em;

// GLASS PASS: RESTORED ORIGINAL TRANSMISSION WITH 2D PLANAR GAUSSIAN FROSTING
if (transmission > 0.01 && useSky) {
// 1. YOUR ORIGINAL, PERFECT, UN-WARPED GLASS PATH (COMPLETELY RESTORED)
vec3 refractDir = refract(-viewDir, normal, 1.0 / clamp(ior, 1.0, 2.5));
vec3 clearGlass = textureLod(skybox, refractDir, roughness * 7.0).bgr;

// 2. ISOLATED 2D NOISE SCATTERING (LEAVES THE Z-DEPTH VECTOR COMPLETELY UNTOUCHED)
vec3 frostedScatter = vec3(0.0);
float totalWeight = 0.0;
float spread = glassRoughness * 0.12; // Calibrated 2D blurring boundary

// Stable analytical sine-wave seed based on the flat texture plane coordinates
float seed = sin(dot(fs_in.TexCoords, vec2(12.9898, 78.233))) * 43758.5453;

for (int s = 1; s <= 16; s++) {
// Generate pure pseudo-random 2D circular offsets
float angle = fract(sin(seed + float(s) * 1.4142)) * 6.2831853; // Random angle in radians
float linearDist = float(s) / 16.0;
float radius = spread * sqrt(linearDist); // Balanced concentric step distribution

// Restrict shifts strictly to a flat 2D tangent coordinate plane
vec3 planeOffset = vec3(cos(angle) * radius, sin(angle) * radius, 0.0);

// GAUSSIAN DISTRIBUTION: Tightly centers the density to erase tracking lines
float weight = exp(-3.0 * linearDist * linearDist);

// Sample the skybox safely without warping the 3D normal vector paths
frostedScatter += textureLod(skybox, refractDir + planeOffset, roughness * 7.0).bgr * weight;
totalWeight += weight;
}

if (totalWeight > 0.0) {
frostedScatter /= totalWeight;
} else {
frostedScatter = clearGlass;
}

// 3. Smoothly transition based on your frosted slider value
vec3 finalGlassOutput = mix(clearGlass, frostedScatter, clamp(glassRoughness * 1.5, 0.0, 1.0));

// Apply your original texture tint properties cleanly
vec3 iblTransmission = finalGlassOutput * (basecolor.rgb * glassColor);
color = mix(color, iblTransmission, transmission) + (iblSpecular * F * transmission);
}

color = (color * (1.0 + color / 2.0)) / (1.0 + color);

float finalAlpha = mix(transp, F.r, transmission);
FragColor = vec4(clamp(color, 0.0, 1.0), finalAlpha);
}


120 changes: 120 additions & 0 deletions phong.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#version 330

// ─────────────────────────────────────────────────────────────────────
// Engine Shader Profile Pipeline Integration
// Core Architecture: MakeHuman 2 Standalone Pipeline BlackPunkduck
// Engineering, Modifications & Systems Integration: Elvaerwyn_MH2 2026 V1.1
// ─────────────────────────────────────────────────────────────────────

struct PointLight {
vec3 position;
vec3 color;
float intensity;
int type;
};

out vec4 FragColor;

in VS_OUT {
vec3 FragPos;
vec3 Normal;
vec2 TexCoords;
} fs_in;

uniform sampler2D Texture;
uniform sampler2D AOTexture;

// PORTED FROM PBR: Normal map sampler layout properties
uniform sampler2D NOTexture;
uniform float NoMult;

// SYNCHRONIZED ARCHITECTURE: Must be defined as a size 3 array to match camera.py loops!
uniform PointLight pointLights[3];

uniform vec3 lightWeight;
uniform vec4 ambientLight;
uniform vec3 viewPos;
uniform bool blinn;
uniform float AOMult;

// PORTED FROM PBR: High-quality normal valuation function
vec3 EvalNormal(vec3 n)
{
vec3 no = texture(NOTexture, fs_in.TexCoords).rgb;

no.r = 1.0 - no.r;
no.g = 1.0 - no.g;

no = normalize(no * 2.0 - 1.0);

vec3 pos_dx = dFdx(fs_in.FragPos);
vec3 pos_dy = dFdy(fs_in.FragPos);
vec2 tex_dx = dFdx(fs_in.TexCoords);
vec2 tex_dy = dFdy(fs_in.TexCoords);
vec3 t = normalize(pos_dx * tex_dy.t - pos_dy * tex_dx.t);
vec3 b = normalize(cross(n, t));

mat3 TBN = mat3(t, b, n);
no = normalize(mix(n, TBN * no, NoMult));
return no;
}

void main()
{
vec3 color = texture(Texture, fs_in.TexCoords).rgb;
float transp = texture(Texture, fs_in.TexCoords).a;
if (transp < 0.01) discard;

float ao = texture(AOTexture, fs_in.TexCoords).r;

// FIXED: Direct swizzling handles vec4 components cleanly without type faults
vec3 ambient = ambientLight.rgb * vec3(ambientLight.a) * color;

// diffuse
vec3 normal = normalize(fs_in.Normal);

// PORTED FROM PBR: Swap smooth normal vector for evaluated normal map details
if (NoMult > 0.05) {
normal = EvalNormal(normal);
}

vec3 diffuse = vec3(0.0, 0.0, 0.0);
vec3 specular = vec3(0.0, 0.0, 0.0);
vec3 viewDir = normalize(viewPos - fs_in.FragPos);

// FIXED VECTOR HOOK: Swapped lightWeight[0] out for native lightWeight.x swizzling!
vec3 specw = vec3(lightWeight.x);

for (int i = 0; i < 3; i++) {
if (pointLights[i].intensity > 0.01) {
// diffuse
vec3 position = pointLights[i].position;
vec3 L = vec3(0.0);
float diff = 0.0;
float l = length(position - fs_in.FragPos) / pointLights[i].intensity;
if (pointLights[i].type == 0) {
L = normalize(position - fs_in.FragPos);
diff = max(dot(L, normal), 0.0) / l;
} else {
L = normalize(position);
diff = clamp(dot(L, normal), 0.0, 1.0) / 2.0;
}
diffuse += diff * pointLights[i].color * color;

// specular
float spec = 0.0;
if(blinn) {
vec3 halfwayDir = normalize(L + viewDir);
// FIXED VECTOR HOOK: Swapped out bracket indices for lightWeight.y
spec = pow(max(dot(normal, halfwayDir), 0.0), lightWeight.y) / l;
} else {
vec3 reflectDir = reflect(-L, normal);
// FIXED VECTOR HOOK: Swapped out bracket indices for lightWeight.y
spec = pow(max(dot(viewDir, reflectDir), 0.0), lightWeight.y) / l;
}
specular += specw * pointLights[i].color * spec;
}
}

FragColor = vec4((ambient + diffuse + specular) * ao * AOMult, transp);
}
Loading