# 5.1 The Shared Vertex Shader

Our Blinn-Phong and Phong shaders can share the same vertex shader.

## Create the vertex shader

Create **blinn.vert** in the shaders directory, you may copy the previous **colour.vert**.

## Input Vertex Attributes

Similar to the previous vertex shader, we are using two vertex attributes. The **position** remains unchanged and the second is changed to **vertex normals**.

```glsl
// Blinn-Phong and Phong shared vertex shader
#version 410

in layout(location=0) vec3 aPos;
in layout(location=1) vec3 aNormal;
```

## &#x20;Uniform Variables

Uniform variables are shared between the C++ program and the GPU shader programs.

Our uniform variables are just the **Model**, **View**, and **Projection** matrices.

We are puting uniform variables after the vertex attributes

```glsl
// M V P matrices
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
```

## Output Vertex Variables to the Fragment Shader

We need to output the fragment position and the normals to the fragment shader. They will be declared as **out** variables. The interpolation of normals will be done by GPU automatically.

```glsl
out vec3 normal;
out vec3 fragPos;
```

## main() function

Now we are implementing our main() function.

### Convert vertex postion to homogeneous

First we are going to convert the poistion to glm::vec4 - the homogeneous coordinates. This is the same as what we have done previously in colour.vert.

```glsl
void main()
    // homogeneous coordinate
    gl_Position = projection * view * model * vec4(aPos, 1.0); 
    
    ...
}
```

### Calculate the fragment position using model matrix

Because we are going to calculate lighting vectors in the world space, we need to calculate fragPos in the world space. This is achieved by using the **modelling** transform matrix.

```glsl
    ...
    
    // colour_vert = colour_in;
    fragPos = vec3(model * vec4(aPos, 1.0));
    
    ...
```

### Calculate the transformed normal vector

Then we also need to transform the normal vector the world space.

For beginners, here we are going to directly use the model matrix. However, this only applies to rigid body transforms. If  there are transforms such as shears, direct use of the model matrix will result in incorrect normal vectors.

```glsl
    ...
    
    // convert 4x4 modelling matrix to 3x3
    mat3 normalMatrix = mat3(model);
    
    // output normal to the fragment shader
    // !! only correct for rigid body transforms
    normal = normalMatrix * aNormal;
}
```

## Full Source Code

```glsl
// Blinn-Phong and Phong shared vertex shader
#version 410

in layout(location=0) vec3 aPos;
in layout(location=1) vec3 aNormal;

// M V P matrices
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

// out vec3 colour_vert;
out vec3 normal;
out vec3 fragPos;

void main()
{
    // homogeneous coordinate
    gl_Position = projection * view * model * vec4(aPos, 1.0); 
    
    // colour_vert = colour_in;
    fragPos = vec3(model * vec4(aPos, 1.0));

    // convert 4x4 modelling matrix to 3x3
    mat3 normalMatrix = mat3(model);
    
    // output normal to the fragment shader
    // !! only correct for rigid body transforms
    normal = normalMatrix * aNormal;
}
```
