# Vase Shader Highlights Tutorial

## Introduction

Swipe to move the 3D blue vase. Colored highlights glance off the vase as it moves. WebGL highlights display with GLSL shaders. Shaders access normals to process lighting. This very short tutorial discusses the vertex and fragment shaders used to highlight the vase. For more details regarding GLSL lighting please read the point light tutorial.

### Vase 3D Model

The original vase was modeled with the 3ds Max
nurbs and lathe modifier,
then exported as a DAE file.
The free 3D Translator

app converted vertex,
texel, and normal values, into arrays, for use with WebGL.

## Vertex Shader

The vertex shader follows.
Attribute `a_normal`

includes X,Y, and Z values
representing a normal for each vertex.
Per vertex normals represent the direction a vertex faces.
Fragments of color render in the fragment shader,
based on values obtained from vertex normals.
Lighting glances off fragments based on a combination
of light location and the direction a fragment faces.
For example, if a fragment faces away from the light,
the fragment displays dark.
If a fragment faces directly toward the light,
the fragment appears bright.
Per vertex normals help determine which direction
fragments face.

Uniform `um3_nmatrix`

is a normal matrix.
The normal matrix is a 3 x 3 matrix derived from
the inverted and transposed *model matrix*.
The model matrix
includes rotation, translation (movement),
scaling, or other transformations applied
to the vase.
The normal matrix
includes rotation, translation (movement),
scaling, or other transformations applied
to the normal.
The normal matrix helps the shader determine
which direction this normal faces.
For example, assume the vase rotated 180^{0}
around. Apply the normal matrix to
rotate the normal 180^{0} too.

Last multiply the normal attribute, `a_normal`

,
by the normal matrix, `um3_nmatrix`

.
Assign the result to varying
`v_normal_transform`

.
The GPU (Graphics Processing Unit) interpolates values,
then sends a varying with the *exact same name*,
to the fragment shader.

Also the fragment shader will have access
to the interpolated position of this particular
vertex.
Varying `v_position`

receives the
product of the current vertex coordinate multiplied
by the model matrix.
Varying `v_position`

represents the
current vertex with any interactive
transformations applied to the vase.

attribute vec3 a_position; attribute vec3 a_normal; attribute vec2 a_tex_coord0; uniform mat4 um4_matrix; uniform mat4 um4_pmatrix; uniform mat3 um3_nmatrix; varying vec2 v_tex_coord0; varying vec3 v_normal_transform; varying vec4 v_position; void main(void) { v_position = um4_matrix * vec4( a_position, 1.0 ); gl_Position = um4_pmatrix * v_position; v_tex_coord0 = a_tex_coord0; // Vertex normal times // transposed inverted model matrix. // Send to the GPU for // interpolation before // fragment shader processing v_normal_transform = um3_nmatrix * a_normal; }

## Fragment Shader

The following code includes the entire fragment shader.
Notice the fragment shader includes
varyings, `v_normal_transform`

and `v_position`

,
with
the same name and type as the vertex shader.
Each varying represents values
assigned in the vertex shader.
However the GPU processes varyings for more precise
values, before passing them to the fragment shader.

This fragment shader includes a number of constant
*vectors*.
A vector represents a line with direction.
Vector `c_light_location`

represents the direction of light rays.
Vector constants `c_light_dcolor, c_light_scolor`

modify the amount of diffuse and specular color applied.

precision mediump float; varying vec2 v_tex_coord0; varying vec3 v_normal_transform; varying vec4 v_position; const float c_shine_amount = 16.0; const vec3 c_ambient = vec3(0.2,0.2,0.4); const vec3 c_light_location = vec3(1.0,1.0,0.5); const vec3 c_light_dcolor = vec3(0.8,0.8,2.0); const vec3 c_light_scolor = vec3(0.9,0.8,0.8); uniform sampler2D u_sampler0; void main(void) { // Difference between // the light's position // and the current // vertex position. vec3 v3_light_vector = normalize( c_light_location - v_position.xyz ); // Normal times transposed // inverted model matrix. vec3 v3_normalized_normal = normalize( v_normal_transform ); float f_specular_weight = 0.0; // Line between view point // and current vertex vec3 v3_direction_eye = normalize( -v_position.xyz ); // Reflection of the // opposite of the light vector // and the normal. vec3 v3_direction_reflection = reflect( -v3_light_vector, v3_normalized_normal ); f_specular_weight = pow( max( dot( v3_direction_reflection, v3_direction_eye ), 0.0 ), c_shine_amount ); float f_diffuse_weight = max( dot( v3_normalized_normal, v3_light_vector ), 0.0 ); vec3 v3_light_weight = c_ambient + c_light_scolor * f_specular_weight + c_light_dcolor * f_diffuse_weight; vec4 color0 = texture2D( u_sampler0, v_tex_coord0 ); gl_FragColor = vec4( color0.rgb * v3_light_weight, color0.a ); }

## Summary

Swipe to move the 3D blue vase. Colored highlights glance off the vase as it moves. WebGL highlights display with GLSL shaders. Shaders access normals to process lighting. This very short tutorial included the vertex and fragment shaders used to highlight the vase.

The original vase was modeled the 3ds Max
nurbs and lathe modifiers, then exported as a DAE file.
The free WebGL Translator

app converted vertex,
texel, and normal values, into arrays, for use with WebGL.

For more details regarding shader lighting please see the point light tutorial.