Reputation: 11
So I'm having trouble with the Phong Model specifically the diffuse component and using the right normal vector and direction to light vector. This is for a school project but I don't care if I don't finish it as long as someone can tell me what I'm doing wrong. I've already tried a few things and the best I do was get half of the larger sphere to shade but in the wrong direction. The brightest intensity is on the outer edge of the circle half and gets darker as it goes to the center when it should be the other way around. It looks like its shading the sphere in lines when I've seen models that look like it's shading in empty circles.
The shading of the second sphere may be hard to see.
Relevant Structures:
struct Ray
{
vec3 origin; // origin of the ray
vec3 dir; // direction of the ray
};
struct Sphere
{
vec3 center;
float radius;
vec3 ka, kd, ks;
vec3 reflectivity;
float alpha;
Sphere(const vec3& ic=vec3(0.0f), const float& ir=0.0f, const vec3& ika=vec3(0.0f), const vec3& ikd=vec3(0.0f), const vec3& iks=vec3(0.0f), const float& ireflectivity=0.1f, const float& ialpha=1.0f):
center(ic), radius(ir), ka(ika), kd(ikd), ks(iks), reflectivity(ireflectivity), alpha(ialpha)
{}
bool intersect(const Ray& ray, float& t0, float& t1);
};
struct PointLight
{
vec3 location;
vec3 id, is;
PointLight(const vec3& iloc=vec3(0.0f), const vec3& iid=vec3(0.0f), const vec3& iis=vec3(0.0f)):
location(iloc), id(iid), is(iis)
{}
};
vec3 color;
vec3 amb = my_sphere.ka* my_ambient_light.ia; // I = ka * ia ambient component
int temp = my_point_lights.size() - 1;
color += amb;
vec3 diff;
for (int i = my_point_lights.size() - 1; i >= 0; i--) {
vec3 n = (ray.origin + ray.dir - my_sphere.center);
normalize(n);
vec3 L = (my_point_lights[temp].location - ray.origin);
normalize(L);
diff += my_sphere.kd * my_point_lights[temp].id * std::max(dot(n, L), 0.0f);
}
color += diff;
Upvotes: 1
Views: 443
Reputation: 15933
What you basically seem to want to do in your shader is compute the diffuse shading of a given point on a sphere. For that you'll basically need two things: First, the surface normal at that point on the sphere you want to shade, and, second, the direction from which the light is falling onto the point you want to shade. Now, before you can go ahead and compute the shading of an object at a given point, you'll generally need to know the actual position of that particular point you want to shade. Since you didn't really provide any explanation what exactly things like ray.dir
actually represent in your code, I'll have to resort to guesswork. I assume that what you're doing is some sort of raytracing in a fragment shader. And I'll have to assume that ray.dir
is not just some vector pointing in the general direction of the ray that hit the sphere at the point you're interested in, but it actually is the vector that will bring you from the start of the ray to the exact hit point on the sphere. Otherwise, you're lacking the most essential information to really do anything, which is the coordinates of the point you wanna shade. In that case, you'll first have to compute where the actual intersection of your ray and your sphere lies.
Now, if we make all these assumptions, and we furthermore assume that all these vectors you have actually represent coordinates in the same coordinate system, then ray.origin + ray.dir - my_sphere.center
should indeed yield a vector pointing from the center of the sphere to the point you want to shade. And that vector should indeed point in the direction of the surface normal of the sphere at the point you want to shade. However, the second vector you need to compute the diffuse shading is a vector pointing into the direction from which the light is falling onto the point you want to shade. That is, a vector pointing from the point to shade to the light source. However, my_point_lights[temp].location - ray.origin
would seem to be a vector pointing from the ray origin to the light source instead.
Apart from that, it should probably be brought to your attention that, contrary to what you seem to be under the impression of, the function normalize(x)
does not modify the vector you pass as an argument. It simply returns another vector that is the normalized version of whatever vector you feed to it. So, most likely, what you actually meant to write is
n = normalize(n);
…
L = normalize(L);
Also, you accumulate values in color
and diff
, yet you never initialize these vectors to anything. You probably meant to initialize them to zero… 😉
Upvotes: 1