OpenGL illuminating opposite faces with the same normal - opengl

Using OpenGL shaders, I want to render a solid cube using diffuse lighting. To do this, I compute the normal of each vertex, and then compute the dot product between this normal and the direction of the light. The problem with this is that each pair of flat surfaces on the cube has the same normal direction, and therefore the same lighting intensity. But if the light source is directly above the cube, then the top surface should be bright, and the bottom surface should be dim -- they should not be the same.
What is the solution?

The normal on top of the cube should have the opposite direction than the one on the bottom. Due to this, the result of the dot product will be 1 for the upper side and -1 for the bottom plane. If you clamp the dot-product to the [0, 1] range, the bottom side will be dark.

Related

Bypass classical deferred shading light volumes

I would like to "bypass" the classical light volume approach of deferred lighting.
Usually, when you want to affect pixels within a pointlight volume, you can simply render a sphere mesh.
I would like to try another way to do that, the idea is to render a cube which encompass the sphere, the cube is "circumscribes" to the sphere so each face's center is a sphere's point. Then you only have to know from your point of view which fragment would be a part of the circle (the sphere on your screen) if you had render the sphere instead.
So the main problem is to know which fragment will have to be discarded.
How could I do that:
Into the fragment shader, I have my "camera" world coordinates, my fragment world coordinates, my sphere world center, and my sphere radius.
Thus I have the straight line whose the orientation vector is modelized by camera-fragment world points.
And I can build my sphere equation.
Finally I can know if the line intersect the sphere.
Is is correct to say that, from my point of view, if the line intersect the sphere, thus this fragment must be considered as an highlighted fragment (a fragment that would have been rendered if I had rendered a sphere instead) ?
Thus the check "lenght(fragment - sphereCenter) <= sphereRadius" doesn't really mean something here because the fragment is not on the sphere.
So what?
The standard deferred shading solution for lights is to render a full-screen quad. The purpose of rendering a sphere instead is to avoid doing a bunch of per-fragment calculations for fragments which are outside of the light source's effect. This means that the center of that sphere is the light source, and its radius represents the maximum distance for which the source has an effect.
So the length from the fragment (that is, reconstructed from your g-buffer data, not the fragment produced by the cube) to the sphere's center is very much relevant. That's the length between the fragment and the light source. If that is larger than the sphere radius (AKA: maximum reach of the light), then you can cull the fragment.
Or you can just let your light attenuation calculations do the same job. After all, in order for lights to not look like they are being cropped, that sphere radius must also be used with some form of light attenuation. That is, when a fragment is at that distance, the attenuation of the light must be either 0 or otherwise negligibly small.
As such... it doesn't matter if you're rendering a sphere, cube, or a full-screen quad. You can either cull the fragment or let the light attenuation do its job.
However, if you want to possibly save performance by discarding the fragment before reading any of the g-buffers, you can do this. Assuming you have access to the camera-space position of the sphere/cube's center in the FS:
Convert the position of the cube's fragment into camera-space. You can do this by reverse-transforming gl_FragCoord, but it'd probably be faster to just pass the camera-space position to the fragment shader. It's not like your VS is doing a lot of work or anything.
Because the camera-space position is in camera space, it already represents a direction from the camera into the scene. So now, use this direction to perform part of ray/sphere intersection. Namely, you stop once you compute the discriminant (to avoid an expensive square-root). The discriminant is:
float A = dot(cam_position, cam_position);
float B = -2 * (dot(cam_position, cam_sphere_center);
float C = (dot(cam_sphere_center, cam_sphere_center)) - (radius * radius)
float Discriminant = (B * B) - 4 * A * C;
If the discriminant is negative, discard the fragment. Otherwise, do your usual stuff.

Need help on how to make a sphere gradient on a gluSphere

Hello I've been trying to find out information on how i can add a gradient from the top of the sphere to the bottom. Is it possible or do i have to texture the sphere?
Sphere sphere = new Sphere();
sphere.setOrientation(GLU.GLU_OUTSIDE);
GL11.glPushMatrix();
GL11.glColor3d(0.0D, 0.0D, 1.0D);
sphere.draw(16.0f, 200, 16);
GL11.glColor3d(1.0D, 1.0D, 1.0D);
GL11.glPopMatrix();
Certainly, it's possible. It's a bit more complicated when you use a GLU sphere, as compared to if you generate your own coordinates and attributes for a sphere, since you need to work with what GLU sphere provides.
You could position a light at, say, the north pole of the sphere, and then adjust your diffuse material properties. This would provide maximal color at the north pole, with a gradual (cosine-based) gradient to the equator, and then dark from the equator to the south pole. The gradient would not be smooth between the poles, but you didn't specify that it needed to be a constant gradient.
Another approach would be to use texture mapping. In particular, if you wanted a constant gradient (i.e., equal gradation from the north to south pole), this is probably the only way to accomplish this when using a GLU sphere without shaders. The solution here is to use one-dimensional texture mapping based on the "vertical" (i.e., t) texture coordinate (e.g., if the s texture coordinate is used for the latitude direction, and the t coordinate is for longitude). Just specify the gradient in your one-dimensional texture.
Of course, if you're using shaders, then it's almost trivial to use the vertex shader to specify a parameter that's convenient for doing this kind of shading in the fragment shader.

2d shadow mapping

I have been wondering about how to implement this with openGL:
I have a map, with a flat floor and walls. Every thing here is 2d, there is no 3d geometry, only 2d poligons that compose the map.
Using the vertex of the polygons I cast shadows, to define the viewable area.
The shadows define the field of view, but since the cells with walls obstructi view, they are also darkened. I can draw the walls on top of the shadows, but doing so would show even walls outside the field of view.
I have been suggested to approach this problem with shadow mapping. I should render the 2D scene into 4 different 1D textures that hold the depth of the distance to the first colliding surface.
The problem is that I have no idea how to render the projection of the 2d scene into the 1D texture. If I use, for example:
gluLookAt (x, y, 0.0, 0.0, x , y+1, 0.0, 0.0, 1.0);
To render the top view, the result is still 2D. Also, nothing would be rendered since all the vertex will be at the same plane, so all surfaces will be ortogonal to the camera.
Do you have any tip or idea of how to do these 2D-to-1D projections? I have been googling for scenarios like this one, but all of them are in 3D enviroments.
Shadow mapping assumes either a directional light, or a spotlight, and you have a point light. But since you only need shadow on the floor, you could model it as a spotlight that hovers e.g. 2 m above the floor and points downwards. All the walls would have to be at least 2 m high. In the first shadow mapping pass, you could render the floor and all the walls into the shadow buffer.
However, I would not go with shadow mapping, but use volumetric shadows instead. If you go from 3D to 2D, a 3D volume becomes a 2D polygon.
Assuming that all the walls are on a regular grid, we can compute view rays from the player's position P to all the corners of walls. For each corner, store the adjacent walls, and ignore all the walls that face away from the player. Then cast rays from P to each corner, convert the rays to polar coordinates, and sort them by their angle, say counter-clockwise. Now go through this sorted list in a sweeping motion, and build the shadow polygon.
The shadow polygon consists either of corner points in this list, or of intersections between a) a line that is parallel to a wall and b) a line that goes through P and a corner. The only thing that makes this a bit complicated is that you have to find the wall that receives the shadow. Since the input is so small, I would probably start with brute force (check the corner against each wall), and see how slow it is. Note that only player-facing walls can cast shadows. Also note that the point closest to the player doesn't need to be visible.
It's probably going to look really cool with a moving character.

OpenGL - Create a border over a textured polygon

I'm working with cocos2d-x 2.0.4. I illustrate what I am trying to do through these two images.
What i want to do is to create a blurred border or a border with a gradient on it programmatically. I have two ideas to do that but I'm not sure if it is the correct way to do. First solution would be to triangulate the polygon containing only the blurred color (concave polygon with a hole in this case) and rendering color on it with a gradient, vertices on the outside of the polygon would be full-alpha and vertices on the inside zero-alpha. The interpolation would do the job of gradient then.
Second solution would be to do it inside the shader itself. All I need is to calculate the distance from a pixel and the closest edge of the polygon to it. Then under a certain threshold I affect pixel white color with a certain alpha value depending on that distance (the shortest the distance is, the biggest alpha is).
Anyway I am very new to openGL stuff and I am afraid that the second solution will end up with big processing time as I have to calculate the distance for every pixel of the polygon. What do you think about this guys? Any ideas the tend to confirm my guesses or am I completely wrong on this?
EDIT:
The solution I finally chose was to use the bisector of every angle (easy to calculate with 3 consecutive vertices) in the polygon and take a point on that bisector that would become a vertex for the inner polygon. Then i take either a outer polygon vertex or a inner polygon vertex to build an array of vertices that can fit the GL_TRIANGLE_STRIP parameter. I put the image below to understand better.
Will a rim lighting shader do what you want? Link to an example
Example code for a GLSL rim lighting shader:
const float rimStart = 0.5f;
const float rimEnd = 1.0f;
const float rimMultiplier = 0.0f;
vec3 rimColor = vec3(1.0f, 1.0f, 1.0f);
float NormalToCam = 1.0 - dot(normalize(outNormal), normalize(camPos - vertexWorldPos.xyz));
float rim = smoothstep(rimStart, rimEnd, NormalToCam) * rimMultiplier;
outColor.rgb += (rimColor * rim);
In order to make this look right from any viewpoint in a 3D scene you will need to perform some silhouetting. This essentially involves using a geometry shader to determine what edges of an object have an adjacent face that is facing the screen and an adjacent face that is not facing the screen. I believe this can be achieved by testing if the dot product between one adjacent face normal and your camera direction is <= 0 while the dot product of the other adjacent face normal and your camera direction is > 0.
Once you know all the edges that outline your polygon at a certain angle, you can tessellate the polygon defined by that border into triangle-strips (still in geometry shader). Then, you will pass a color per vertex to your fragment shader; where all vertices lying on the border pass the border color at full alpha and non-border points pass a color at zero alpha . The fragment shader will interpolate from border color to center alpha color at intermediate fragments giving you the gradient you want. Your total approach should be something like this:
Draw object with non-border shader program as the background color.
Enable alpha blending.
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
Draw object with silhouetting program determining the edges that make up the borders with the border color, and drawing non-border points as zero alpha.
glDisable(GL_BLEND);

OpenGL Lighting Quads

just a quick question. I have a quad in 3D OpenGL scene. I define a normal to the plane counter clockwise. So that the normal points out one side of the plane. In the direction of my light source. The quad is light but on both sides.
Should it not only be light on one side of the quad? Or is it the fact that a primitive like a quad is finitely thin and thus looks light from both sides. So if i wanted to make a wall I would use two quads. One for each side of the wall.
Thanks
The default OpenGL lighting behavior for two sided polygons is to calculate lighting for the front face and apply it to both sides.
You can get around this by using a front and back polygon with seperate normals for each of your double sided polygons.
Alternatively, you can enable GL_LIGHT_MODEL_TWO_SIDE for lighting calculations using glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE) . See the glLightModel reference for more information.