I am no where near a GLSL expert, but my vertex shader is shown below. The “layout (location =) in” statements define a vertex. Remember that the vertex shader is nothing but a vertex processor; its primary job is to process vertices.
Also realize that a vertex is a piece of data that’s definition is largely up to you as the programmer. Vertices always have positions (at least I’ve never seen a case where they do not), but pretty much everything else about them is up to how you want to define them. I defined mine as having positions, UV coordinates, normals, and colors. What you put in them and in what order is basically up to you. You just have to get the shader and the OGL code to agree.
#version 450 core
layout (location = 0) in vec3 Pos;
layout (location = 1) in vec2 UV;
layout (location = 2) in vec3 Normal;
layout (location = 3) in vec4 Color;
uniform mat4 WorldMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;
smooth out vec2 TextureCoordinates;
smooth out vec3 VertexNormal;
smooth out vec4 RGBAColor;
smooth out vec4 PositionRelativeToCamera;
out vec3 WorldSpacePosition;
void main()
{
gl_Position = WorldMatrix * vec4(Pos, 1.0f); //Apply object's world matrix.
WorldSpacePosition = gl_Position.xyz; //Save the position of the vertex in the 3D world just calculated. Convert to vec3 because it will be used with other vec3's.
gl_Position = ViewMatrix * gl_Position; //Apply the view matrix for the camera.
PositionRelativeToCamera = gl_Position;
gl_Position = ProjectionMatrix * gl_Position; //Apply the Projection Matrix to project it on to a 2D plane.
TextureCoordinates = UV; //Pass through the texture coordinates to the fragment shader.
VertexNormal = mat3(WorldMatrix) * Normal; //Rotate the normal according to how the model is oriented in the 3D world.
RGBAColor = Color; //Pass through the color to the fragment shader.
};
As to how OGL passes the vertices to the shader, it is by defining a vertex buffer and filling it. You can optionally have an index buffer that tells it what order to send the vertices in. Here’s my OGL code to define the buffers and the vertices:
bool HandCodedObjectClass::DefineMesh(int NumberOfVertices, GLfloat* VertexList, int NumberOfIndices, GLuint* IndexList, Texture2DClass* ColorMap)
{
Texture = ColorMap;
VerticesInMesh = NumberOfVertices;
IndicesInMesh = NumberOfIndices;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, NumberOfVertices * sizeof(GLfloat) * 12, VertexList, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 12, nullptr); //Vertex Position.
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 12, (GLvoid*)(sizeof(GLfloat) * 3)); //Vertex UV.
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 12, (GLvoid*)(sizeof(GLfloat) * 5)); //Vertex Normal.
glEnableVertexAttribArray(2);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 12, (GLvoid*)(sizeof(GLfloat) * 8)); //Vertex RGBA color.
glEnableVertexAttribArray(3);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*NumberOfIndices, IndexList, GL_STATIC_DRAW);
return true;
}
Once you have your buffers loaded with the vertices, you set your uniforms to pass in the non-vertex data and then draw.
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, IndicesInMesh, GL_UNSIGNED_INT, nullptr);
glBindVertexArray(0); //Release it.