Skip to content

Commit

Permalink
Create inspection lighting scene
Browse files Browse the repository at this point in the history
Greatly improves brightness and contrast. Colours are now rendered accurately in 3D visualization.

Employs three-point lighting principles: key light, back light, and fill light.

We use multiple key and fill lights, not for visual aesthetics, but to improve illumination of scene for inspection when rotating objects.
  • Loading branch information
n8bot committed Dec 11, 2021
1 parent 08a3af8 commit 60e11fe
Show file tree
Hide file tree
Showing 6 changed files with 351 additions and 115 deletions.
86 changes: 61 additions & 25 deletions resources/shaders/gouraud.vs
@@ -1,22 +1,28 @@
#version 110

#define INTENSITY_CORRECTION 0.6

// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION)
#define LIGHT_TOP_SHININESS 20.0

// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
//#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION)
//#define LIGHT_FRONT_SHININESS 5.0

#define INTENSITY_AMBIENT 0.3

const vec3 ZERO = vec3(0.0, 0.0, 0.0);
// Two key lights
const vec3 LIGHT_KEY_TOP_DIR = vec3(-1.0, 0.75, 1.0);
const vec3 LIGHT_KEY_BOT_DIR = vec3(-1.0, -0.75, 1.0);
#define LIGHT_KEY_DIFFUSE 0.16
#define LIGHT_KEY_SPECULAR 0.008

// One back light
const vec3 LIGHT_BACK_DIR = vec3(0.75, 0.5, -1.0);
#define LIGHT_BACK_DIFFUSE 0.3
#define LIGHT_BACK_SPECULAR 0.015

// Four fill lights
const vec3 LIGHT_FILL_TOP_FRONT_DIR = vec3(1.0, 0.75, 1.0);
const vec3 LIGHT_FILL_BOT_FRONT_DIR = vec3(1.0, -0.75, 1.0);
const vec3 LIGHT_FILL_TOP_MIDDLE_DIR = vec3(0.0, 1.0, 0.8);
const vec3 LIGHT_FILL_BOT_MIDDLE_DIR = vec3(0.0, -1.0, 0.8);
const vec3 LIGHT_FILL_CENTER_FRONT_DIR = vec3(0.0, 0.0, 1.0);

#define LIGHT_FILL_DIFFUSE 0.1
#define LIGHT_FILL_SPECULAR 0.004

#define LIGHT_SHININESS 7.0
#define INTENSITY_AMBIENT 0.3

struct SlopeDetection
{
Expand All @@ -33,7 +39,7 @@ uniform vec2 z_range;
// Clipping plane - general orientation. Used by the SLA gizmo.
uniform vec4 clipping_plane;

// x = diffuse, y = specular;
// x = diffuse, y = specular
varying vec2 intensity;

varying vec3 clipping_planes_dots;
Expand All @@ -47,18 +53,48 @@ void main()
{
// First transform the normal into camera space and normalize the result.
eye_normal = normalize(gl_NormalMatrix * gl_Normal);
vec3 position = (gl_ModelViewMatrix * gl_Vertex).xyz;

// Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
// Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0);

intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
vec3 position = (gl_ModelViewMatrix * gl_Vertex).xyz;
intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS);
// Ambient light
intensity.x = INTENSITY_AMBIENT;

// Key lights
float NdotL = max(dot(eye_normal, LIGHT_KEY_TOP_DIR), 0.0);
intensity.x += NdotL * LIGHT_KEY_DIFFUSE;
intensity.y = LIGHT_KEY_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_KEY_TOP_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

NdotL = max(dot(eye_normal, LIGHT_KEY_BOT_DIR), 0.0);
intensity.x += NdotL * LIGHT_KEY_DIFFUSE;
intensity.y += LIGHT_KEY_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_KEY_BOT_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

// Back light
NdotL = max(dot(eye_normal, LIGHT_BACK_DIR), 0.0);
intensity.x += NdotL * LIGHT_BACK_DIFFUSE;
intensity.y += LIGHT_BACK_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_BACK_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

// Fill lights
NdotL = max(dot(eye_normal, LIGHT_FILL_TOP_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FILL_DIFFUSE;
intensity.y += LIGHT_FILL_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_FILL_TOP_FRONT_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

NdotL = max(dot(eye_normal, LIGHT_FILL_BOT_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FILL_DIFFUSE;
intensity.y += LIGHT_FILL_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_FILL_BOT_FRONT_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

NdotL = max(dot(eye_normal, LIGHT_FILL_TOP_MIDDLE_DIR), 0.0);
intensity.x += NdotL * LIGHT_FILL_DIFFUSE;
intensity.y += LIGHT_FILL_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_FILL_TOP_MIDDLE_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

NdotL = max(dot(eye_normal, LIGHT_FILL_BOT_MIDDLE_DIR), 0.0);
intensity.x += NdotL * LIGHT_FILL_DIFFUSE;
intensity.y += LIGHT_FILL_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_FILL_BOT_MIDDLE_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

// Perform the same lighting calculation for the 2nd light source (no specular applied).
NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
NdotL = max(dot(eye_normal, LIGHT_FILL_CENTER_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FILL_DIFFUSE;
intensity.y += LIGHT_FILL_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_FILL_CENTER_FRONT_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

model_pos = gl_Vertex;
// Point in homogenous coordinates.
Expand Down
76 changes: 58 additions & 18 deletions resources/shaders/gouraud_light.vs
@@ -1,38 +1,78 @@
#version 110

#define INTENSITY_CORRECTION 0.6
// Two key lights
const vec3 LIGHT_KEY_TOP_DIR = vec3(-1.0, 0.75, 1.0);
const vec3 LIGHT_KEY_BOT_DIR = vec3(-1.0, -0.75, 1.0);
#define LIGHT_KEY_DIFFUSE 0.16
#define LIGHT_KEY_SPECULAR 0.008

// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION)
#define LIGHT_TOP_SHININESS 20.0
// One back light
const vec3 LIGHT_BACK_DIR = vec3(0.75, 0.5, -1.0);
#define LIGHT_BACK_DIFFUSE 0.3
#define LIGHT_BACK_SPECULAR 0.015

// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
// Four fill lights
const vec3 LIGHT_FILL_TOP_FRONT_DIR = vec3(1.0, 0.75, 1.0);
const vec3 LIGHT_FILL_BOT_FRONT_DIR = vec3(1.0, -0.75, 1.0);
const vec3 LIGHT_FILL_TOP_MIDDLE_DIR = vec3(0.0, 1.0, 0.8);
const vec3 LIGHT_FILL_BOT_MIDDLE_DIR = vec3(0.0, -1.0, 0.8);
const vec3 LIGHT_FILL_CENTER_FRONT_DIR = vec3(0.0, 0.0, 1.0);

#define INTENSITY_AMBIENT 0.3
#define LIGHT_FILL_DIFFUSE 0.1
#define LIGHT_FILL_SPECULAR 0.004

// x = tainted, y = specular;
#define LIGHT_SHININESS 7.0
#define INTENSITY_AMBIENT 0.3

// x = diffuse, y = specular
varying vec2 intensity;

void main()
{
// First transform the normal into camera space and normalize the result.
vec3 normal = normalize(gl_NormalMatrix * gl_Normal);
vec3 position = (gl_ModelViewMatrix * gl_Vertex).xyz;

// Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
// Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0);

intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
vec3 position = (gl_ModelViewMatrix * gl_Vertex).xyz;
intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS);
// Ambient light
intensity.x = INTENSITY_AMBIENT;

// Key lights
float NdotL = max(dot(normal, LIGHT_KEY_TOP_DIR), 0.0);
intensity.x += NdotL * LIGHT_KEY_DIFFUSE;
intensity.y = LIGHT_KEY_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_KEY_TOP_DIR, normal)), 0.0), LIGHT_SHININESS);

NdotL = max(dot(normal, LIGHT_KEY_BOT_DIR), 0.0);
intensity.x += NdotL * LIGHT_KEY_DIFFUSE;
intensity.y += LIGHT_KEY_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_KEY_BOT_DIR, normal)), 0.0), LIGHT_SHININESS);

// Back light
NdotL = max(dot(normal, LIGHT_BACK_DIR), 0.0);
intensity.x += NdotL * LIGHT_BACK_DIFFUSE;
intensity.y += LIGHT_BACK_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_BACK_DIR, normal)), 0.0), LIGHT_SHININESS);

// Fill lights
NdotL = max(dot(normal, LIGHT_FILL_TOP_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FILL_DIFFUSE;
intensity.y += LIGHT_FILL_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_FILL_TOP_FRONT_DIR, normal)), 0.0), LIGHT_SHININESS);

NdotL = max(dot(normal, LIGHT_FILL_BOT_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FILL_DIFFUSE;
intensity.y += LIGHT_FILL_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_FILL_BOT_FRONT_DIR, normal)), 0.0), LIGHT_SHININESS);

NdotL = max(dot(normal, LIGHT_FILL_TOP_MIDDLE_DIR), 0.0);
intensity.x += NdotL * LIGHT_FILL_DIFFUSE;
intensity.y += LIGHT_FILL_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_FILL_TOP_MIDDLE_DIR, normal)), 0.0), LIGHT_SHININESS);

NdotL = max(dot(normal, LIGHT_FILL_BOT_MIDDLE_DIR), 0.0);
intensity.x += NdotL * LIGHT_FILL_DIFFUSE;
intensity.y += LIGHT_FILL_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_FILL_BOT_MIDDLE_DIR, normal)), 0.0), LIGHT_SHININESS);

// Perform the same lighting calculation for the 2nd light source (no specular applied).
NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
NdotL = max(dot(normal, LIGHT_FILL_CENTER_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FILL_DIFFUSE;
intensity.y += LIGHT_FILL_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_FILL_CENTER_FRONT_DIR, normal)), 0.0), LIGHT_SHININESS);

gl_Position = ftransform();
}
78 changes: 59 additions & 19 deletions resources/shaders/gouraud_light_instanced.vs
@@ -1,18 +1,28 @@
#version 110

#define INTENSITY_CORRECTION 0.6
// Two key lights
const vec3 LIGHT_KEY_TOP_DIR = vec3(-1.0, 0.75, 1.0);
const vec3 LIGHT_KEY_BOT_DIR = vec3(-1.0, -0.75, 1.0);
#define LIGHT_KEY_DIFFUSE 0.16
#define LIGHT_KEY_SPECULAR 0.008

// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION)
#define LIGHT_TOP_SHININESS 20.0
// One back light
const vec3 LIGHT_BACK_DIR = vec3(0.75, 0.5, -1.0);
#define LIGHT_BACK_DIFFUSE 0.3
#define LIGHT_BACK_SPECULAR 0.015

// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
// Four fill lights
const vec3 LIGHT_FILL_TOP_FRONT_DIR = vec3(1.0, 0.75, 1.0);
const vec3 LIGHT_FILL_BOT_FRONT_DIR = vec3(1.0, -0.75, 1.0);
const vec3 LIGHT_FILL_TOP_MIDDLE_DIR = vec3(0.0, 1.0, 0.8);
const vec3 LIGHT_FILL_BOT_MIDDLE_DIR = vec3(0.0, -1.0, 0.8);
const vec3 LIGHT_FILL_CENTER_FRONT_DIR = vec3(0.0, 0.0, 1.0);

#define INTENSITY_AMBIENT 0.3
#define LIGHT_FILL_DIFFUSE 0.1
#define LIGHT_FILL_SPECULAR 0.004

#define LIGHT_SHININESS 7.0
#define INTENSITY_AMBIENT 0.3

// vertex attributes
attribute vec3 v_position;
Expand All @@ -21,26 +31,56 @@ attribute vec3 v_normal;
attribute vec3 i_offset;
attribute vec2 i_scales;

// x = tainted, y = specular;
// x = diffuse, y = specular
varying vec2 intensity;

void main()
{
// First transform the normal into camera space and normalize the result.
vec3 eye_normal = normalize(gl_NormalMatrix * v_normal);
vec4 world_position = vec4(v_position * vec3(vec2(1.5 * i_scales.x), 1.5 * i_scales.y) + i_offset - vec3(0.0, 0.0, 0.5 * i_scales.y), 1.0);
vec3 eye_position = (gl_ModelViewMatrix * world_position).xyz;

// Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
// Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0);

// Ambient light
intensity.x = INTENSITY_AMBIENT;

intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
vec4 world_position = vec4(v_position * vec3(vec2(1.5 * i_scales.x), 1.5 * i_scales.y) + i_offset - vec3(0.0, 0.0, 0.5 * i_scales.y), 1.0);
vec3 eye_position = (gl_ModelViewMatrix * world_position).xyz;
intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS);
// Key lights
float NdotL = max(dot(eye_normal, LIGHT_KEY_TOP_DIR), 0.0);
intensity.x += NdotL * LIGHT_KEY_DIFFUSE;
intensity.y = LIGHT_KEY_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_KEY_TOP_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

NdotL = max(dot(eye_normal, LIGHT_KEY_BOT_DIR), 0.0);
intensity.x += NdotL * LIGHT_KEY_DIFFUSE;
intensity.y += LIGHT_KEY_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_KEY_BOT_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

// Back light
NdotL = max(dot(eye_normal, LIGHT_BACK_DIR), 0.0);
intensity.x += NdotL * LIGHT_BACK_DIFFUSE;
intensity.y += LIGHT_BACK_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_BACK_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

// Fill lights
NdotL = max(dot(eye_normal, LIGHT_FILL_TOP_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FILL_DIFFUSE;
intensity.y += LIGHT_FILL_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_FILL_TOP_FRONT_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

NdotL = max(dot(eye_normal, LIGHT_FILL_BOT_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FILL_DIFFUSE;
intensity.y += LIGHT_FILL_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_FILL_BOT_FRONT_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

NdotL = max(dot(eye_normal, LIGHT_FILL_TOP_MIDDLE_DIR), 0.0);
intensity.x += NdotL * LIGHT_FILL_DIFFUSE;
intensity.y += LIGHT_FILL_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_FILL_TOP_MIDDLE_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

NdotL = max(dot(eye_normal, LIGHT_FILL_BOT_MIDDLE_DIR), 0.0);
intensity.x += NdotL * LIGHT_FILL_DIFFUSE;
intensity.y += LIGHT_FILL_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_FILL_BOT_MIDDLE_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

// Perform the same lighting calculation for the 2nd light source (no specular applied).
NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
NdotL = max(dot(eye_normal, LIGHT_FILL_CENTER_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FILL_DIFFUSE;
intensity.y += LIGHT_FILL_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_FILL_CENTER_FRONT_DIR, eye_normal)), 0.0), LIGHT_SHININESS);

gl_Position = gl_ProjectionMatrix * vec4(eye_position, 1.0);
}

0 comments on commit 60e11fe

Please sign in to comment.