Took at the files shader_4_1.vert i shader_4_1.frag. Note how normal vectors are sent from vertex shader to fragment shader with variable interpNormal
. Files shader_4_2.vert i shader_4_2.frag won’t be used for now.
Send to the fragment shader a variable of type uniform vec3
(name it eg. lightDir
), it will contain the light direction:
Do it the same way as objectColor
is sent. Only difference is that the light direction is independent form a object, thus call of glUniform3f
should be done only once before any draw call. Call glUseProgram(program)
before sending the value.
As a light direction pick any unit vector. (You can take any nonzero vector and normalize it)
normalize the normal vector before using it (averaging during rasterization could have changed their size).
Intensity is equal to a dot product of surface normal vector and inverse light direction vector. Use the function dot
.
Intensity cannot be negative. clamp it to zero from bellow with max function: x = max(x, 0.0)
(Normal vectors are in local model space and the light direction vector is in world space)
All vertex normal vectors have to be transformed into world space:
Send the model matrix of the object drawn as a separate variable to the vertex shader (uniform mat4
).
Multiply the normal vector in the shader with the model matrix before sending it to the fragment shader.
The w coordinate of the normal vector has to be set to 0 before multipication with the model matrix. This is because the normal vector is a direction and not a point in homogeneous coordinates. We do not want to translate it during homogenization.
Send the camera position (cameraPos
) as another variable to the fragment shader.
Analogously to the normal vectors of the vertex shader, send the vertex positions from vertex to fragment shader (vertexPosition) in world space (multiplied with the modelMatrix). This time around the vectors represent points and not directions - the w coordinate of the vertex positions has to be set to 1. In the result of rasterization we will recive fragment position in the fragment shader.
Calculate vector V (view direciton vecor) as a normalized difference of the camera position and the fragment position.
Obtain the reflected light direction R using the glsl function reflect
. Remember to that light direction vector must be inverse.
Calculate the light intensity: dot product of V i R, clamped to zero ( max(...,0.0)
)and then raised to high power (np. 8, 50, 1000), which is a measure of brilliancy.
Instead of sending (in lightDir
) light direction, send the sun position to the fragment shader (the same that you set in the exercise above) as uniform vec3
(call it lightPos
).
Calculate the light direction by subtracting the sun position from the fragment position. Normalize the result and save it in the lightDir
variable.
Sun will be black, don’t worry about it, it will be fixed in the next task.
Goal of this exercise is to create a shader (shader_4_sun.vert_ i shader_4_sun.frag), that will be responsible only for rendering the sun. Previous shaders (shader_4_1.vert_ i shader_4_1.frag) should still render other objects.
Files shader_4_sun.vert and shader_4_sun.frag are identical to 4_1 before your modifications, they will be starting point for sun shader.
Create global variable GLuint programSun
which will be used to store sun shader address. Create program with shaderLoader.CreateProgram
analogously to creation of program
from shader_4_1.vert i shader_4_1.frag (input values are paths to vertex and fragment shaders shader_4_sun.vert i shader_4_sun.frag).
-function drawObject
uses the global function program
, to point drawing shaders. Add a function argument, which should contain a program address used in rendering.
-add appropriate program to drawObject
calls.
On the picture bellow you can see a sun. It is darker on the corners, try to get a similar effect. Vectors from previous points will be useful, especially normal vector and the vector V.