I am implementing my first rasterizer, and I’ve run right into a 2 points with Phong shading that I do not know methods to debug. First, specular lighting appears to be utterly lacking. Second, there’s an edge case, the place diffuse lighting is not utilized to a face for some motive (nor specular, solely ambient). I do have a side-by-side comparability of what it ought to appear to be, with the right model being rendered utilizing my raytracer. The one distinction between the two scenes is that the spheres are changed with sphere fashions for the rasterizer.
In my triangle drawing operate, I calculate the depth worth like this:
depth := coefficient_a * da + coefficient_b * db + coefficient_c * dc
z := 1 / depth
x_camera := f32(x) * VIEWPORT_WIDTH/CANVAS_WIDTH * z/VIEWPORT_DISTANCE
y_camera := f32(y) * VIEWPORT_HEIGHT/CANVAS_HEIGHT * z/VIEWPORT_DISTANCE
regular := coefficient_a * na + coefficient_b * nb + coefficient_c * nc
depth := compute_light({x_camera, y_camera, z}, regular, digital camera, lights, materials)
pixel(goal, depth_buffer, level, depth, depth * materials.colour)
My compute_light operate appears like this:
compute_light :: proc(level, regular: t.Vector3, digital camera: scene.Digital camera, lights: []scene.Gentle, materials: scene.Materials) -> f32 {
depth: f32 = 0
for mild in lights {
light_vector: t.Vector3
local_intensity: f32
change l in mild {
case scene.Ambient_Light:
depth += l.depth
proceed
case scene.Point_Light:
light_vector = scene.matrix_apply(digital camera.inverse, l.place) - level
local_intensity = l.depth
case scene.Directional_Light:
light_vector = scene.matrix_apply(digital camera.inverse_vector, l.path)
local_intensity = l.depth
}
ndl := linalg.dot(regular, light_vector)
if ndl > 0 {
scale := ndl / (linalg.size(regular)*linalg.size(light_vector))
depth += scale * local_intensity
}
if materials.specularity > 0 {
reflection_vector := 2 * ndl * regular - light_vector
// We're in digital camera house, so the digital camera is at (0, 0, 0)
point_to_camera := -point
rdc := linalg.dot(reflection_vector, point_to_camera)
if rdc > 0 {
scale := math.pow(rdc / (linalg.size(reflection_vector)*linalg.size(point_to_camera)), materials.specularity)
depth += scale * local_intensity
}
}
}
return min(depth, 1)
}
I can present extra code, or examine the entire mission right here: https://github.com/diniamo/rendr/tree/f4750aaf5f8004849de8a148051581fb7cf4d4b8/rasterizer




