In order to apply specular lighting you will need 4 additional pieces of information:
- The fragment position.
- The camera position.
- The specular intensity of the pyramid material.
- The shininess of the pyramid material.
1. Add the fragment position
1.1. Modify the vertex shader
- Open the main.cpp file.
- Modify the fragment 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"
"out vec3 vFragPos;\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"
"vFragPos = (model * vec4(pos, 1.0)).xyz;\n"
"}\n";
1.2. Modify the fragment shader
static const GLchar fragmentShaderSource[] =
"#version 310 es\n"
"precision mediump float;\n"
"in vec4 vColor;\n"
"in vec2 vTexCoords;\n"
"in vec3 vNorm;\n"
"in vec3 vFragPos;\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";
2. Add the material
2.1. Modify the fragment shader
- 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"
"in vec3 vFragPos;\n"
"out vec4 color;\n"
"struct DirectionalLight\n"
"{\n"
"vec3 color;\n"
"float intensity;\n"
"vec3 direction;\n"
"float diffuseIntensity;\n"
"};\n"
"struct Material\n"
"{\n"
"float specularIntensity;\n"
"float shininess;\n"
"};\n"
"uniform sampler2D textureSampler;\n"
"uniform DirectionalLight directionalLight;\n"
"uniform Material material;\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";
2.2. Set the uniform variables
- Declare the following global variables:
/* code */ GLint uniformLightColor, uniformLightIntensity, uniformLightDirection, uniformDiffuseLightIntensity; GLint uniformMaterialSpecularIntensity, uniformMaterialShininess; glm::mat4 projectionMatrix; /* code */
- Modify the createProgram function as follows:
/* code */ uniformDiffuseLightIntensity = glGetUniformLocation(program, "directionalLight.diffuseIntensity"); uniformMaterialSpecularIntensity = glGetUniformLocation(program, "material.specularIntensity"); uniformMaterialShininess = glGetUniformLocation(program, "material.shininess"); return; /* code */
- Modify the Java_dev_anastasioscho_glestriangle_NativeLibrary_nOnDrawFrame function as follows:
/* code */
glm::mat4 viewMatrix = glm::lookAt(cameraPosition, cameraTarget, worldUp);
glUniformMatrix4fv(uniformView, 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniform1f(uniformMaterialSpecularIntensity, 1.0f);
glUniform1f(uniformMaterialShininess, 32.0f);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
/* code */
3. Add the camera position
3.1. Modify the fragment shader
- 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"
"in vec3 vFragPos;\n"
"out vec4 color;\n"
"struct DirectionalLight\n"
"{\n"
"vec3 color;\n"
"float intensity;\n"
"vec3 direction;\n"
"float diffuseIntensity;\n"
"};\n"
"struct Material\n"
"{\n"
"float specularIntensity;\n"
"float shininess;\n"
"};\n"
"uniform sampler2D textureSampler;\n"
"uniform DirectionalLight directionalLight;\n"
"uniform Material material;\n"
"uniform vec3 cameraPosition;\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";
3.2. Set the uniform variable
- Declare the following global variable:
/* code */ GLint uniformLightColor, uniformLightIntensity, uniformLightDirection, uniformDiffuseLightIntensity; GLint uniformMaterialSpecularIntensity, uniformMaterialShininess, uniformCameraPosition; glm::mat4 projectionMatrix; /* code */
- Modify the createProgram function as follows:
/* code */ uniformDiffuseLightIntensity = glGetUniformLocation(program, "directionalLight.diffuseIntensity"); uniformMaterialSpecularIntensity = glGetUniformLocation(program, "material.specularIntensity"); uniformMaterialShininess = glGetUniformLocation(program, "material.shininess"); uniformCameraPosition = glGetUniformLocation(program, "cameraPosition"); return; /* code */
- Modify the Java_dev_anastasioscho_glestriangle_NativeLibrary_nOnDrawFrame function as follows:
/* code */
glm::mat4 viewMatrix = glm::lookAt(cameraPosition, cameraTarget, worldUp);
glUniformMatrix4fv(uniformView, 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniform1f(uniformMaterialSpecularIntensity, 1.0f);
glUniform1f(uniformMaterialShininess, 32.0f);
glUniform3f(uniformCameraPosition, cameraPosition.x, cameraPosition.y, cameraPosition.z);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
/* code */
4. Apply specular 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"
"in vec3 vFragPos;\n"
"out vec4 color;\n"
"struct DirectionalLight\n"
"{\n"
"vec3 color;\n"
"float intensity;\n"
"vec3 direction;\n"
"float diffuseIntensity;\n"
"};\n"
"struct Material\n"
"{\n"
"float specularIntensity;\n"
"float shininess;\n"
"};\n"
"uniform sampler2D textureSampler;\n"
"uniform DirectionalLight directionalLight;\n"
"uniform Material material;\n"
"uniform vec3 cameraPosition;\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"
"vec4 specularColor = vec4(0.0f, 0.0f, 0.0f, 0.0f);\n"
"if (diffuseFactor > 0.0f) {\n"
"vec3 fragToEye = normalize(cameraPosition - vFragPos);\n"
"vec3 reflectedVertex = normalize(reflect(directionalLight.direction, normalize(vNorm)));\n"
"float specularFactor = dot(fragToEye, reflectedVertex);\n"
"if (specularFactor > 0.0f) {\n"
"specularFactor = pow(specularFactor, material.shininess);"
"specularColor = vec4(directionalLight.color * material.specularIntensity * specularFactor, 1.0f);\n"
"}\n"
"}\n"
"color = texture(textureSampler, vTexCoords) * (ambientColor + diffuseColor + specularColor);\n"
"}\n";
Leave a Reply