Sunday, December 14, 2025
spot_img

Phong shading: lacking specular lighting, skipped face


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.

Phong shading: lacking specular lighting, skipped face

raytracer output (expected)

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

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisement -spot_img

Latest Articles