1. Modify the directional light
1.1. Modify the fragment shader
- Open the main.cpp file.
- Modify the fragment shader source code as follows:
static const GLchar fragmentShaderSource[] =
"#version 310 es\n"
"precision mediump float;\n"
"in vec4 vColor;\n"
"in vec2 vTexCoords;\n"
"out vec4 color;\n"
"struct DirectionalLight\n"
"{\n"
"vec3 color;\n"
"float intensity;\n"
"vec3 direction;\n"
"float diffuseIntensity;\n"
"};\n"
"uniform sampler2D textureSampler;\n"
"uniform DirectionalLight directionalLight;\n"
"void main()\n"
"{\n"
"vec4 ambientColor = vec4(directionalLight.color, 1.0f) * directionalLight.intensity;\n"
"color = texture(textureSampler, vTexCoords) * ambientColor;\n"
"}\n";
1.2. Set the uniform variables
- Declare the following global variables:
/* code */ GLint uniformModel, uniformProjection, uniformView; GLint uniformLightColor, uniformLightIntensity, uniformLightDirection, uniformDiffuseLightIntensity; glm::mat4 projectionMatrix; /* code */
- Modify the createProgram function as follows:
/* code */ uniformLightIntensity = glGetUniformLocation(program, "directionalLight.intensity"); uniformLightDirection = glGetUniformLocation(program, "directionalLight.direction"); uniformDiffuseLightIntensity = glGetUniformLocation(program, "directionalLight.diffuseIntensity"); return; /* code */
- Modify the Java_dev_anastasioscho_glestriangle_NativeLibrary_nOnDrawFrame function as follows:
/* code */ glUniform3f(uniformLightColor, 1.0f, 1.0f, 1.0f); glUniform1f(uniformLightIntensity, 1.0f); glUniform3f(uniformLightDirection, 2.0f, 0.3f, -2.0f); glUniform1f(uniformDiffuseLightIntensity, 1.0f); currentAngle += angleStep; if (currentAngle >= 360.0f) currentAngle -= 360.0f; /* code */
2. Add the normals
2.1. Modify the vertices data
- Modify the createTriangle function as follows:
void createTriangle() {
/* code */
GLfloat vertices[] = {
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-1.0f, -1.0f, 1.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, -1.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, -1.0f, -1.0f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f
};
glGenVertexArrays(1, &triangleVAO);
glBindVertexArray(triangleVAO);
glGenBuffers(1, &triangleIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, triangleIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glGenBuffers(1, &triangleVBO);
glBindBuffer(GL_ARRAY_BUFFER, triangleVBO);
glBufferData(GL_ARRAY_BUFFER, 40 * sizeof(GL_FLOAT), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 8, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 8, (void*)(sizeof(GL_FLOAT) * 3));
glEnableVertexAttribArray(1);
/* code */
return;
}
Info
The last three floats are the x, y and z coordinates of the normal vector. Initially the are all zero. You will calculate them next.
- Add the following function to calculate the average normals:
void calculateAverageNormals(unsigned int *indices, unsigned int totalIndices, GLfloat *vertices, unsigned int totalVertices, unsigned int vertexLength, unsigned int normalOffset) {
for (size_t i = 0; i < totalIndices; i += 3) {
unsigned int in0 = indices[i] * vertexLength;
unsigned int in1 = indices[i + 1] * vertexLength;
unsigned int in2 = indices[i + 2] * vertexLength;
glm::vec3 v1(vertices[in1] - vertices[in0], vertices[in1 + 1] - vertices[in0 + 1], vertices[in1 + 2] - vertices[in0 + 2]);
glm::vec3 v2(vertices[in2] - vertices[in0], vertices[in2 + 1] - vertices[in0 + 1], vertices[in2 + 2] - vertices[in0 + 2]);
glm::vec3 normal = glm::cross(v1, v2);
normal = glm::normalize(normal);
in0 += normalOffset; in1 += normalOffset; in2 += normalOffset;
vertices[in0] += normal.x; vertices[in0 + 1] += normal.y; vertices[in0 + 2] += normal.z;
vertices[in1] += normal.x; vertices[in1 + 1] += normal.y; vertices[in1 + 2] += normal.z;
vertices[in2] += normal.x; vertices[in2 + 1] += normal.y; vertices[in2 + 2] += normal.z;
}
for (size_t i = 0; i < (totalVertices / vertexLength); i++) {
unsigned int nOffset = (i * vertexLength) + normalOffset;
glm::vec3 vec(vertices[nOffset], vertices[nOffset + 1], vertices[nOffset + 2]);
vec = glm::normalize(vec);
vertices[nOffset] = vec.x; vertices[nOffset + 1] = vec.y; vertices[nOffset + 2] = vec.z;
}
}
- Modify the createTriangle function to call the function:
/* code */
GLfloat vertices[] = {
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-1.0f, -1.0f, 1.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, -1.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, -1.0f, -1.0f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f
};
calculateAverageNormals(indices, 12, vertices, 40, 8, 5);
glGenVertexArrays(1, &triangleVAO);
glBindVertexArray(triangleVAO);
/* code */
2.2. Modify the vertex shader
- Modify the vertex shader source code as follows:
static const GLchar vertexShaderSource[] =
"#version 310 es\n"
"layout (location = 0) in vec3 pos;\n"
"layout (location = 1) in vec2 texCoords;\n"
"layout (location = 2) in vec3 norm;\n"
"out vec4 vColor;\n"
"out vec2 vTexCoords;\n"
"out vec3 vNorm;\n"
"uniform mat4 model;\n"
"uniform mat4 projection;\n"
"uniform mat4 view;\n"
"void main()\n"
"{\n"
"gl_Position = projection * view * model * vec4(pos, 1.0);\n"
"vColor = vec4(clamp(pos, 0.0, 1.0), 1.0);\n"
"vTexCoords = texCoords;\n"
"vNorm = mat3(transpose(inverse(model))) * norm;\n"
"}\n";
- Modify the fragment shader source code as follows:
static const GLchar fragmentShaderSource[] =
"#version 310 es\n"
"precision mediump float;\n"
"in vec4 vColor;\n"
"in vec2 vTexCoords;\n"
"in vec3 vNorm;\n"
"out vec4 color;\n"
"struct DirectionalLight\n"
"{\n"
"vec3 color;\n"
"float intensity;\n"
"vec3 direction;\n"
"float diffuseIntensity;\n"
"};\n"
"uniform sampler2D textureSampler;\n"
"uniform DirectionalLight directionalLight;\n"
"void main()\n"
"{\n"
"vec4 ambientColor = vec4(directionalLight.color, 1.0f) * directionalLight.intensity;\n"
"color = texture(textureSampler, vTexCoords) * ambientColor;\n"
"}\n";
- Modify the createTriangle function as follows:
/* code */ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 8, (void*)(sizeof(GL_FLOAT) * 3)); glEnableVertexAttribArray(1); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 8, (void*)(sizeof(GL_FLOAT) * 5)); glEnableVertexAttribArray(2); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindVertexArray(0); /* code */
3. Apply diffuse lighting
- Modify the fragment shader source code as follows:
static const GLchar fragmentShaderSource[] =
"#version 310 es\n"
"precision mediump float;\n"
"in vec4 vColor;\n"
"in vec2 vTexCoords;\n"
"in vec3 vNorm;\n"
"out vec4 color;\n"
"struct DirectionalLight\n"
"{\n"
"vec3 color;\n"
"float intensity;\n"
"vec3 direction;\n"
"float diffuseIntensity;\n"
"};\n"
"uniform sampler2D textureSampler;\n"
"uniform DirectionalLight directionalLight;\n"
"void main()\n"
"{\n"
"vec4 ambientColor = vec4(directionalLight.color, 1.0f) * directionalLight.intensity;\n"
"float diffuseFactor = max(dot(normalize(vNorm), normalize(directionalLight.direction)), 0.0f);\n"
"vec4 diffuseColor = vec4(directionalLight.color, 1.0f) * directionalLight.diffuseIntensity * diffuseFactor;\n"
"color = texture(textureSampler, vTexCoords) * (ambientColor + diffuseColor);\n"
"}\n";
Leave a Reply