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