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