mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-06-12 23:13:32 +00:00
Adjust
This commit is contained in:
@@ -1,94 +1,89 @@
|
||||
#version 110
|
||||
|
||||
/**
|
||||
* SSAO (Screen Space Ambient Occlusion) Shader - GLSL 110 version
|
||||
* Uses depth-based sampling with adaptive radius and weighting
|
||||
* Compatible with OpenGL 2.1 and older hardware
|
||||
* SSAO Shader - GLSL 110 version with highlight protection
|
||||
* Preserves brightness on upward-facing surfaces (top areas)
|
||||
*/
|
||||
|
||||
uniform sampler2D color_texture; // Original scene color
|
||||
uniform sampler2D depth_texture; // Depth buffer texture
|
||||
uniform vec2 inv_tex_size; // 1.0/width, 1.0/height - for UV offset calculation
|
||||
uniform float z_near; // Near clipping plane distance
|
||||
uniform float z_far; // Far clipping plane distance
|
||||
uniform sampler2D color_texture;
|
||||
uniform sampler2D depth_texture;
|
||||
uniform sampler2D normal_texture;
|
||||
uniform vec2 inv_tex_size;
|
||||
uniform float z_near;
|
||||
uniform float z_far;
|
||||
|
||||
varying vec2 tex_coord; // Texture coordinates from vertex shader
|
||||
varying vec2 tex_coord;
|
||||
|
||||
/**
|
||||
* Convert linear depth buffer value to world/view space depth
|
||||
* Uses standard OpenGL perspective projection reverse mapping
|
||||
*/
|
||||
float linearize_depth(float depth)
|
||||
{
|
||||
float z = depth * 2.0 - 1.0; // Convert to NDC [-1, 1] range
|
||||
float z = depth * 2.0 - 1.0;
|
||||
return (2.0 * z_near * z_far) / (z_far + z_near - z * (z_far - z_near));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// Sample base color at current fragment
|
||||
vec3 base = texture2D(color_texture, tex_coord).rgb;
|
||||
|
||||
// Linearize center pixel depth for accurate world-space comparisons
|
||||
float depth_center = linearize_depth(texture2D(depth_texture, tex_coord).r);
|
||||
|
||||
// Adaptive sampling radius: larger radius for distant objects (perspective effect)
|
||||
// Closer objects need smaller radius to capture fine details
|
||||
// Sample normal at current fragment (range: -1 to 1)
|
||||
vec3 normal_center = texture2D(normal_texture, tex_coord).rgb * 2.0 - 1.0;
|
||||
|
||||
// Calculate how much the surface faces upward
|
||||
// up_factor = 1.0 for surfaces pointing straight up (0,0,1)
|
||||
// up_factor = 0.0 for surfaces pointing down or sideways
|
||||
float up_factor = max(0.0, normal_center.z); // Assuming Z is up axis
|
||||
// Alternative: if Y is up, use normal_center.y
|
||||
|
||||
// Enhance brightness on top surfaces (reduce AO effect)
|
||||
// Top surfaces get only 30% of AO, bottom surfaces get 100%
|
||||
float highlight_protection = mix(1.0, 0.3, up_factor);
|
||||
|
||||
// Adaptive sampling radius
|
||||
float radius = mix(1.5, 4.0, depth_center / z_far);
|
||||
|
||||
// Circular sampling pattern (unit circle) with diagonal weighting
|
||||
// Offsets normalized to unit circle for uniform directional sampling
|
||||
vec2 offsets[8];
|
||||
offsets[0] = vec2( 1.0, 0.0); // Right
|
||||
offsets[1] = vec2( 0.707, 0.707); // Top-right diagonal
|
||||
offsets[2] = vec2( 0.0, 1.0); // Top
|
||||
offsets[3] = vec2(-0.707, 0.707); // Top-left diagonal
|
||||
offsets[4] = vec2(-1.0, 0.0); // Left
|
||||
offsets[5] = vec2(-0.707,-0.707); // Bottom-left diagonal
|
||||
offsets[6] = vec2( 0.0, -1.0); // Bottom
|
||||
offsets[7] = vec2( 0.707,-0.707); // Bottom-right diagonal
|
||||
offsets[0] = vec2( 1.0, 0.0);
|
||||
offsets[1] = vec2( 0.707, 0.707);
|
||||
offsets[2] = vec2( 0.0, 1.0);
|
||||
offsets[3] = vec2(-0.707, 0.707);
|
||||
offsets[4] = vec2(-1.0, 0.0);
|
||||
offsets[5] = vec2(-0.707,-0.707);
|
||||
offsets[6] = vec2( 0.0, -1.0);
|
||||
offsets[7] = vec2( 0.707,-0.707);
|
||||
|
||||
float occlusion = 0.0;
|
||||
int valid_samples = 0;
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
// Apply radius and convert to UV space
|
||||
vec2 uv = tex_coord + offsets[i] * inv_tex_size * radius;
|
||||
|
||||
// Clamp to texture edges to prevent border artifacts
|
||||
uv = clamp(uv, vec2(0.001), vec2(0.999));
|
||||
|
||||
// Sample and linearize neighbor depth
|
||||
float sample_depth = linearize_depth(texture2D(depth_texture, uv).r);
|
||||
|
||||
// Calculate depth difference (positive if neighbor is closer to camera)
|
||||
float depth_diff = max(0.0, depth_center - sample_depth);
|
||||
|
||||
// Adaptive threshold: larger tolerance for distant objects
|
||||
// smoothstep creates soft occlusion falloff
|
||||
float threshold = 0.015 * (0.5 + depth_center / z_far);
|
||||
float contribution = smoothstep(0.001, threshold, depth_diff);
|
||||
|
||||
// Weight diagonal samples less (they're further in screen space)
|
||||
// Reduces over-occlusion at 45-degree angles
|
||||
float diagonal_weight = 1.0 - abs(offsets[i].x * offsets[i].y) * 0.5;
|
||||
|
||||
occlusion += contribution * diagonal_weight;
|
||||
valid_samples++;
|
||||
}
|
||||
|
||||
// Average occlusion from all valid samples
|
||||
if (valid_samples > 0)
|
||||
occlusion /= float(valid_samples);
|
||||
|
||||
// Apply AO intensity curve
|
||||
// 0.55 intensity factor - subtle effect that preserves original lighting
|
||||
float ambient_occlusion = 1.0 - occlusion * 0.55;
|
||||
ambient_occlusion = clamp(ambient_occlusion, 0.55, 1.0);
|
||||
// Apply highlight protection - top surfaces get much less darkening
|
||||
float ao_intensity = 0.55 * highlight_protection;
|
||||
float ambient_occlusion = 1.0 - occlusion * ao_intensity;
|
||||
|
||||
// Gamma-style curve for more natural appearance
|
||||
ambient_occlusion = pow(ambient_occlusion, 1.1);
|
||||
// Different min values for top vs bottom surfaces
|
||||
float ao_min = mix(0.45, 0.70, up_factor); // Bottom: 0.45, Top: 0.70
|
||||
ambient_occlusion = clamp(ambient_occlusion, ao_min, 1.0);
|
||||
|
||||
// Boost brightness on top surfaces (optional)
|
||||
float brightness_boost = 1.0 + up_factor * 0.15; // 15% extra brightness on top
|
||||
ambient_occlusion = pow(ambient_occlusion, 1.1) * brightness_boost;
|
||||
ambient_occlusion = clamp(ambient_occlusion, 0.45, 1.05);
|
||||
|
||||
// Final composite: modulate base color with AO factor
|
||||
gl_FragColor = vec4(base * ambient_occlusion, 1.0);
|
||||
}
|
||||
@@ -1,93 +1,99 @@
|
||||
#version 140
|
||||
|
||||
/**
|
||||
* SSAO (Screen Space Ambient Occlusion) Shader - GLSL 140 version
|
||||
* Uses texelFetch for precise pixel access and better performance
|
||||
* Requires OpenGL 3.1+ / GLSL 1.40
|
||||
* SSAO Shader - GLSL 140 version with highlight protection
|
||||
* Preserves brightness on upward-facing surfaces for better visual quality
|
||||
*/
|
||||
|
||||
uniform sampler2D color_texture; // Original scene color
|
||||
uniform sampler2D depth_texture; // Depth buffer texture
|
||||
uniform float z_near; // Near clipping plane distance
|
||||
uniform float z_far; // Far clipping plane distance
|
||||
uniform sampler2D color_texture;
|
||||
uniform sampler2D depth_texture;
|
||||
uniform sampler2D normal_texture;
|
||||
uniform float z_near;
|
||||
uniform float z_far;
|
||||
|
||||
in vec2 tex_coord; // Texture coordinates from vertex shader
|
||||
out vec4 frag_color; // Final fragment color output
|
||||
in vec2 tex_coord;
|
||||
out vec4 frag_color;
|
||||
|
||||
/**
|
||||
* Convert linear depth buffer value to world/view space depth
|
||||
* Same math as 110 version but with modern syntax
|
||||
*/
|
||||
float linearize_depth(float depth)
|
||||
{
|
||||
float z = depth * 2.0 - 1.0; // Convert to NDC [-1, 1] range
|
||||
float z = depth * 2.0 - 1.0;
|
||||
return (2.0 * z_near * z_far) / (z_far + z_near - z * (z_far - z_near));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// Get exact pixel coordinates using gl_FragCoord (pixel-perfect access)
|
||||
ivec2 pixel = ivec2(gl_FragCoord.xy);
|
||||
|
||||
// Use texelFetch for direct pixel access without texture filtering
|
||||
// Much faster and more precise than texture2D for depth buffers
|
||||
float center_depth = linearize_depth(texelFetch(depth_texture, pixel, 0).r);
|
||||
|
||||
// Adaptive radius in pixel space (not UV space)
|
||||
// int cast ensures exact pixel offsets without floating point errors
|
||||
// Sample normal buffer (stored as RGB in 0-1 range, convert to -1 to 1)
|
||||
vec3 normal_center = texelFetch(normal_texture, pixel, 0).rgb * 2.0 - 1.0;
|
||||
normal_center = normalize(normal_center);
|
||||
|
||||
// Calculate upward-facing factor
|
||||
// Assumes Z-up coordinate system (typical for 3D printing)
|
||||
float up_factor = clamp(normal_center.z * 1.5, 0.0, 1.0); // Boosted for better response
|
||||
|
||||
// Alternative if using Y-up: float up_factor = clamp(normal_center.y * 1.5, 0.0, 1.0);
|
||||
|
||||
// Adaptive radius in pixel space
|
||||
int radius = int(mix(2.0, 5.0, center_depth / z_far));
|
||||
|
||||
// Optimized sampling pattern with more samples (12 vs 8)
|
||||
// Includes both cardinal directions and diagonals at different distances
|
||||
// Optimized sampling pattern
|
||||
const ivec2 offsets[12] = ivec2[](
|
||||
ivec2(1, 0), ivec2(-1, 0), ivec2(0, 1), ivec2(0, -1), // Cardinal directions (distance 1)
|
||||
ivec2(1, 1), ivec2(-1, 1), ivec2(1, -1), ivec2(-1, -1), // Diagonals (distance 1.414)
|
||||
ivec2(2, 0), ivec2(-2, 0), ivec2(0, 2), ivec2(0, -2) // Far cardinal (distance 2)
|
||||
ivec2(1, 0), ivec2(-1, 0), ivec2(0, 1), ivec2(0, -1),
|
||||
ivec2(1, 1), ivec2(-1, 1), ivec2(1, -1), ivec2(-1, -1),
|
||||
ivec2(2, 0), ivec2(-2, 0), ivec2(0, 2), ivec2(0, -2)
|
||||
);
|
||||
|
||||
float occlusion = 0.0;
|
||||
int valid_samples = 0;
|
||||
|
||||
for (int i = 0; i < 12; i++) {
|
||||
// Calculate neighbor pixel position with adaptive radius
|
||||
ivec2 sample_pixel = pixel + offsets[i] * radius;
|
||||
|
||||
// Boundary check to prevent reading outside framebuffer
|
||||
// Avoids artifacts at screen edges
|
||||
if (sample_pixel.x < 0 || sample_pixel.y < 0)
|
||||
continue;
|
||||
|
||||
// Direct pixel fetch - no filtering, exact depth value
|
||||
float sample_depth = linearize_depth(texelFetch(depth_texture, sample_pixel, 0).r);
|
||||
|
||||
// Depth difference (positive = neighbor is in front)
|
||||
// Sample normal at neighbor
|
||||
vec3 normal_sample = texelFetch(normal_texture, sample_pixel, 0).rgb * 2.0 - 1.0;
|
||||
|
||||
// Direction from center to sample in screen space
|
||||
vec2 dir_2d = normalize(vec2(sample_pixel - pixel));
|
||||
|
||||
// Reduce occlusion when normals are similar (planar surfaces)
|
||||
float normal_similarity = dot(normal_center, normal_sample);
|
||||
float planar_factor = smoothstep(0.7, 0.95, normal_similarity);
|
||||
|
||||
float depth_diff = max(0.0, center_depth - sample_depth);
|
||||
|
||||
// Adaptive threshold based on distance
|
||||
// Distant objects need larger threshold due to depth compression
|
||||
float threshold = 0.02 * (0.5 + center_depth / z_far);
|
||||
float contribution = smoothstep(0.001, threshold, depth_diff);
|
||||
|
||||
// Smoothstep for soft occlusion falloff
|
||||
occlusion += smoothstep(0.001, threshold, depth_diff);
|
||||
// Reduce contribution on planar surfaces and top areas
|
||||
float top_factor = 1.0 - up_factor * 0.6; // 60% less occlusion on tops
|
||||
contribution *= (1.0 - planar_factor * 0.5) * top_factor;
|
||||
|
||||
occlusion += contribution;
|
||||
valid_samples++;
|
||||
}
|
||||
|
||||
// Calculate final AO factor
|
||||
if (valid_samples > 0) {
|
||||
// Average occlusion and apply intensity (0.5 = subtle effect)
|
||||
float ao_factor = 1.0 - (occlusion / float(valid_samples)) * 0.5;
|
||||
ao_factor = clamp(ao_factor, 0.58, 1.0);
|
||||
float ao_factor = 1.0 - (occlusion / float(valid_samples)) * 0.45;
|
||||
|
||||
// Apply power curve for better visual response
|
||||
ao_factor = pow(ao_factor, 1.15);
|
||||
occlusion = ao_factor;
|
||||
// Brighter minimum for top surfaces
|
||||
float ao_min = mix(0.50, 0.75, up_factor);
|
||||
ao_factor = clamp(ao_factor, ao_min, 1.0);
|
||||
|
||||
// Additional brightness boost for upward-facing surfaces
|
||||
float brightness_boost = 1.0 + up_factor * 0.2;
|
||||
ao_factor = pow(ao_factor, 1.1) * brightness_boost;
|
||||
|
||||
occlusion = clamp(ao_factor, 0.45, 1.05);
|
||||
} else {
|
||||
occlusion = 1.0; // No samples available, no occlusion
|
||||
occlusion = 1.0;
|
||||
}
|
||||
|
||||
// Sample color using standard filtering (better for colors)
|
||||
vec3 color = texture(color_texture, tex_coord).rgb;
|
||||
|
||||
// Apply ambient occlusion to final color
|
||||
frag_color = vec4(color * occlusion, 1.0);
|
||||
}
|
||||
Reference in New Issue
Block a user