I have a shader which calculates diffuse lighting values. It consists of a vertex and a fragment shader that calculate the lighting intensity on a per-vertex basis. However, as expected, if I have a large GL_TRIANGLE with a light position, say, just above the center of the triangle, the light that should illuminate it does not appear because the light values are smoothly interpolated across the surface of the triangle based on the vertex calculations.
So my question is this- how can a primitive be lit by a light source at a position other than at one of its vertices?
When you do lighting at vertices, you're doing Phong lighting, which is computing a color at the vertices, and then merely interpolating the colors computed at the vertices (i.e., Gouraud shading) across all the pixels in the primitive. If you were to compute the lighting color at each pixel, you'd get Phong shading. Given your scenario, if you move the lighting computations from the vertex shader to the fragment shader, and interpolate the normal across the primitive you should get much better results.
If you make the vertex normal a varying variable and normalize it in the fragment shader, and then do your lighting computations, you should get much better results.
Related
I am implementing a Phong Shader in GLSL for an assignment, but I don't get the same specular reflection as I should. The way I understood it, it's the same as Gouraud Shading, but instead of doing all the calculations in the vertex shader, you do them in the fragment shader, so that you interpolate the normals and then apply the phong model at each pixel. As part of the assignment I had to develop also the Gouraud shader and that works as supposed and I thought you just needed to put the vertex shader code into the fragment shader, but that doesn't seem to be the case.
What I do in the vertex shader is that I simply transform the vertex position into view coordinates and I apply the transpose inverse of the model view matrix to the vertex normal. Then, in the fragment shader I apply just the view transform to the light position and use these coordinates to calculate the vectors needed in the Phong model The lighting is almost correct, but some specular light is missing. All the parameters have been tested, so I would assume it's the light's position that is wrong, however I have no idea why my code wouldn't work when it does so in the other shader. Also, I know this isn't the most efficient way of doing it (pre-computing the normal matrix would be faster), I'm just trying to first get it to work properly.
The problem is the way how the light source position is calculated. The following code
vec3 l = normalize(mat3(VMatrix)*light);
treats light as a direction (by normalizing it and because the translation part of the view matrix is ignored), but it actually is a position. The correct code should be something like
vec3 l = (VMatrix * vec4(light, 1.0)).xyz
I'm familiar with vertex and fragment shaders but still confused about how a fragment shader determines the amount of fragments from the output of vertex shader.
If I have 3 vertices and I draw a triangle primitive in GLSL, then vertex shader will run three times for every vertex and then fragment shader will run many times (depending upon the number of fragments, once for each fragment).
I want to know how fragment shader determines the fragments? Does it use gl_Position? If I don't set gl_Position in my vertex shader does fragment shader still be able to generate fragments or not?
Is gl_Position is compulsory to set every time in vertex shader?
You're talking about the step in rasterization known as scan-conversion. The GPU takes the positions generated by your vertex shader and interpolates their attributes to produce the fragments that are passed to your fragment shader. So yes, it is essential for you to set gl_Position in the vertex shader.
After converting the coordinates of a triangle to window coordinates, scan conversion takes the triangle and breaks it up based on the arrangement of window pixels over the output image that the triangle covers. Source.
I am trying to shade a sphere. I calculated the normals to each vertex of the sphere, but I don't understand how the other pixels on the facets will be shaded. Any help on this ? I am using OpenGL 3+.
For Gouraud shading the lighting model is computed (as a color) for each vertex of the triangle and then linearly interpolated over the triangle pixels.
In OpenGL you simply compute the ligthting model for each vertex in a vertex shader as a color vector passed to a fragment shader as a varying and then the linear interpolation is done automatically "for free".
If you want Phong shading, you pass the vertex normal directly to the fragment shader which will be automatically linearly interpolated too and then you compute the lighting model in the fragment shader using this interpolated normal.
This question already has answers here:
What are Vertex and Pixel shaders?
(6 answers)
Closed 5 years ago.
I've read some tutorials regarding Cg, yet one thing is not quite clear to me.
What exactly is the difference between vertex and fragment shaders?
And for what situations is one better suited than the other?
A fragment shader is the same as pixel shader.
One main difference is that a vertex shader can manipulate the attributes of vertices. which are the corner points of your polygons.
The fragment shader on the other hand takes care of how the pixels between the vertices look. They are interpolated between the defined vertices following specific rules.
For example: if you want your polygon to be completely red, you would define all vertices red. If you want for specific effects like a gradient between the vertices, you have to do that in the fragment shader.
Put another way:
The vertex shader is part of the early steps in the graphic pipeline, somewhere between model coordinate transformation and polygon clipping I think. At that point, nothing is really done yet.
However, the fragment/pixel shader is part of the rasterization step, where the image is calculated and the pixels between the vertices are filled in or "coloured".
Just read about the graphics pipeline here and everything will reveal itself:
http://en.wikipedia.org/wiki/Graphics_pipeline
Vertex shader is done on every vertex, while fragment shader is done on every pixel. The fragment shader is applied after vertex shader. More about the shaders GPU pipeline link text
Nvidia Cg Tutorial:
Vertex transformation is the first processing stage in the graphics hardware pipeline. Vertex transformation performs a sequence of math operations on each vertex. These operations include transforming the vertex position into a screen position for use by the rasterizer, generating texture coordinates for texturing, and lighting the vertex to determine its color.
The results of rasterization are a set of pixel locations as well as a set of fragments. There is no relationship between the number of vertices a primitive has and the number of fragments that are generated when it is rasterized. For example, a triangle made up of just three vertices could take up the entire screen, and therefore generate millions of fragments!
Earlier, we told you to think of a fragment as a pixel if you did not know precisely what a fragment was. At this point, however, the distinction between a fragment and a pixel becomes important. The term pixel is short for "picture element." A pixel represents the contents of the frame buffer at a specific location, such as the color, depth, and any other values associated with that location. A fragment is the state required potentially to update a particular pixel.
The term "fragment" is used because rasterization breaks up each geometric primitive, such as a triangle, into pixel-sized fragments for each pixel that the primitive covers. A fragment has an associated pixel location, a depth value, and a set of interpolated parameters such as a color, a secondary (specular) color, and one or more texture coordinate sets. These various interpolated parameters are derived from the transformed vertices that make up the particular geometric primitive used to generate the fragments. You can think of a fragment as a "potential pixel." If a fragment passes the various rasterization tests (in the raster operations stage, which is described shortly), the fragment updates a pixel in the frame buffer.
Vertex Shaders and Fragment Shaders are both feature of 3-D implementation that does not uses fixed-pipeline rendering. In any 3-D rendering vertex shaders are applied before fragment/pixel shaders.
Vertex shader operates on each vertex. If you have a fixed polygon mesh and you want to deform it in a shader, you have to implement it in vertex shader. I.e. any physical change in vertex appearances can be done in vertex shaders.
Fragment shader takes the output from the vertex shader and associates colors, depth value of a pixel, etc. After these operations the fragment is send to Framebuffer for display on the screen.
Some operation, as for example lighting calculation, you can perform in vertex shader as well as fragment shader. But fragment shader provides better result than the vertex shader.
In rendering images via 3D hardware you typically have a mesh (point, polygons, lines) these are defined by vertices. To manipulate vertices individually typically for motions in a model or waves in an ocean you can use vertex shaders. These vertices can have static colour or colour assigned by textures, to manipulate vertex colours you use fragment shaders. At the end of the pipeline when the view goes to screen you can also use fragment shaders.
In a tutorial there was a diffuse value calculation of the type
float diffuse_value = max(dot(vertex_normal, vertex_light_position), 0.0);
..on the vertex shader.
That was supposed to be making per vertex lighting if later on the fragment shader..
gl_FragColor = gl_Color * diffuse_value;
Then when he moved the first line - appropriately (by outputting vertex_normal and vertex_light_position to fragment) - to the the fragment shader, it is supposed to be transforming the method to "per pixel shading".
How is that so? The first method appears to be doing the diffuse_value calculation every pixel anyway!
diffuse_value in the first case is computed in the vertex shader. So it's only done per vertex.
After the vertex shader outputs values, the rasterizer takes those values (3 per triangle for each vector) and interpolates (in a perspective correct manner) them to provide different values for each pixel. As it happens, interpolating vectors like that (the normal and the light direction vectors) is not proper, because it loses their normalized property. Many implementations will actually normalize the vectors first thing in the fragment shader.
But it's worse to interpolate the dot of the 2 vectors (what the vector lighting effectively does). Say for example that your is N=+Z for all your vertices and L=norm(Z-X) on one and L=norm(Z+X) on another.
N.L = 1/sqrt(2) for both vertices.
Interpolating that will give you a flat lighting, whereas actually interpolating N and L separately and renormalizing will give you the result you'd expect, a lighting that peaks exactly in the middle of the polygon. (because the interpolation of norm(Z-X) and norm(Z+X) will give exactly Z once normalized).
Well ... Code in a vertex shader is only evaluated per-vertex, with the input values of that vertex.
But when moved to a fragment shader, it is evaluated per-fragment, i.e. per pixel, with input values appropriately interpolated between vertices.
At least that is my understanding, I'm quite rusty with shader programming though.
If diffuse_value is computed in vertex shader, that means it is computed per vertex. Then, it is linearly interpolated on pixels of triangle and feed into pixel shader. (If you don't have per-pixel normals, that's all you can do.) Then, in pixel shader, polygon color (interpolated too) is modulated with that diffuse_value.