diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,10 @@
 # Changelog for keid-render-basic
 
+## 0.1.1.2
+
+- Fix ambient occlusion in LitMaterial shader setup.
+- Fix roughness clamping in Lit shader.
+
 ## 0.1.1.1
 
 - Update timer to match `keid-core`.
diff --git a/keid-render-basic.cabal b/keid-render-basic.cabal
--- a/keid-render-basic.cabal
+++ b/keid-render-basic.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           keid-render-basic
-version:        0.1.1.1
+version:        0.1.1.2
 synopsis:       Basic rendering programs for Keid engine.
 category:       Game Engine
 author:         IC Rainbow
diff --git a/src/Render/Code/Lit.hs b/src/Render/Code/Lit.hs
--- a/src/Render/Code/Lit.hs
+++ b/src/Render/Code/Lit.hs
@@ -186,12 +186,12 @@
       vec2(roughness, max(dot(normal, rayDir), 0.0))
     ).rg;
     vec3 F = F_SchlickR(max(dot(normal, rayDir), 0.0), F0, roughness);
-    vec3 specular = occlusion * reflection * (F * ibl.x + ibl.y);
+    vec3 specular = nonOcclusion * reflection * (F * ibl.x + ibl.y);
 
     vec3 kD = (1.0 - F) * (1.0 - metallic);
 
     // Diffuse based on irradiance
-    vec3 diffuseI = occlusion * irradiance * albedo;
+    vec3 diffuseI = nonOcclusion * irradiance * albedo;
     vec3 ambient = kD * diffuseI + specular;
 
     // Combine with ambient
@@ -299,7 +299,8 @@
         // D = Normal distribution (Distribution of the microfacets)
         float D = D_GGX(dotNH, roughness);
         // G = Geometric shadowing term (Microfacets shadowing)
-        float G = G_SchlicksmithGGX(dotNL, dotNV, roughness);
+        float rroughness = max(0.05, roughness);
+        float G = G_SchlicksmithGGX(dotNL, dotNV, rroughness);
         // F = Fresnel factor (Reflectance depending on angle of incidence)
         vec3 F = F_Schlick(dotNV, F0);
         vec3 spec = D * F * G / (4.0 * dotNL * dotNV + 0.001);
diff --git a/src/Render/Lit/Colored/Pipeline.hs b/src/Render/Lit/Colored/Pipeline.hs
--- a/src/Render/Lit/Colored/Pipeline.hs
+++ b/src/Render/Lit/Colored/Pipeline.hs
@@ -151,7 +151,7 @@
       vec4 baseColor = fColor; // XXX: assuming premultiplied alpha
       float metallic = fMetallicRoughness[0];
       float roughness = fMetallicRoughness[1];
-      float occlusion = 1.0 - 0.0;
+      float nonOcclusion = 1.0;
 
       vec3 normal = normalize(fNormal);
 
diff --git a/src/Render/Lit/Material/Pipeline.hs b/src/Render/Lit/Material/Pipeline.hs
--- a/src/Render/Lit/Material/Pipeline.hs
+++ b/src/Render/Lit/Material/Pipeline.hs
@@ -161,7 +161,7 @@
       vec4 baseColor = material.baseColor;
       float metallic = material.metallicRoughness[0];
       float roughness = material.metallicRoughness[1];
-      float occlusion = 0;
+      float nonOcclusion = 1.0;
       vec4 emissive = material.emissive;
 
       if (material.baseColorTex > -1) {
@@ -188,21 +188,22 @@
           ),
           fTexCoord0
         ).rgb;
+        // XXX: assuming sRGB textures, even for AMR
         packed = pow(packed, vec3(1.0/2.2));
-        occlusion = packed.r;
+        nonOcclusion -= packed.r;
         metallic *= packed.b;
         roughness *= packed.g;
       }
 
       // // TODO: combine with MR as channel R.
-      // occlusion = texture(
+      // float occlusion = texture(
       //   sampler2D(
       //     textures[nonuniformEXT(max(0, material.ambientOcclusionTex))],
       //     samplers[0]
       //   ),
       //   fTexCoord0
       // ).r;
-      // // occlusion = pow(occlusion, 1.0/2.2);
+      // nonOcclusion -= pow(occlusion, 1.0/2.2);
 
       if (material.emissiveTex > -1) {
         emissive *= texture(
diff --git a/src/Render/Lit/Textured/Pipeline.hs b/src/Render/Lit/Textured/Pipeline.hs
--- a/src/Render/Lit/Textured/Pipeline.hs
+++ b/src/Render/Lit/Textured/Pipeline.hs
@@ -175,7 +175,7 @@
       // TODO: get from textures
       float metallic = 0.0;
       float roughness = 0.6;
-      float occlusion = 1.0 - 0.0;
+      float nonOcclusion = 1.0;
 
       vec3 normal = normalize(fNormal);
 
