Page 1 of 5 12345 LastLast
Results 1 to 10 of 46

Thread: Issues with smooth edges spotlights in OpenGL

  1. #1
    Junior Member Newbie
    Join Date
    Apr 2015
    Posts
    23

    Question Issues with smooth edges spotlights in OpenGL

    I am currently working on adding lighting to my project and am still at the basics (getting everything to render properly) with lighting. I am using LWJGL (Java) on a Windows 7 machine, more detailed information at the bottom.

    So the issue is, when trying to create a spotlight with a cutoff (limited angle affected by the light) I get very hard edges, almost like stairs, as seen in this picture:

    light.jpg

    There is no ambient light (using
    Code :
    glLightModel(GL_LIGHT_MODEL_AMBIENT, colorToFloatBuffer(new Color(0.0f, 0.0f, 0.0f, 1.0f)))
    ) and I also disabled spot exponent (specifies how the light is distributed in the cone) and all attenuations to make the effect clearer and the background is a big white image (made black by the lack of ambient light; I am also wondering why I even need ot use an image at all in order to see the light).

    And that is obviously not what it is supposed to look like (it should be a triangle-like shape, right?) and I have no idea why. Additionally, I scale the context before rendering anything in order to maintain using orhtographic coordinates in a perspective (GLUT) view for visual effects.

    This is how I setup my light:

    Code :
    	glEnable(GL_LIGHTING);
    	glEnable(GL_COLOR_MATERIAL);
     
    	glLight(glLightID, GL_AMBIENT, colorToFloatBuffer(Color.blue));
    	glLight(glLightID, GL_DIFFUSE, colorToFloatBuffer(Color.black));
    	glLight(glLightID, GL_SPECULAR, colorToFloatBuffer(Color.black));
     
    	glLight(glLightID, GL_POSITION, floatBuffer.put(position.x).put(position.y).put(0.0f).put(1.0f));
     
    	glLight(glLightID, GL_SPOT_DIRECTION, otherFloatBuffer.put(1.0f, 0.0f, 0.0f)); 
    	glLightf(glLightID, GL_SPOT_EXPONENT, lightSource.getSpotExponent());
    	glLightf(glLightID, GL_SPOT_CUTOFF, 22.5f);
     
    	glLightf(glLightID, GL_CONSTANT_ATTENUATION, 1.0f);
    	glLightf(glLightID, GL_LINEAR_ATTENUATION, 0.0f);
    	glLightf(glLightID, GL_QUADRATIC_ATTENUATION, 0.0f);

    Also, the Form Posting Guide told me to post specific information about the system I am using, so here it goes:

    OS: Windows 7 | OS_VERSION: 6.1
    JAVA_VERSION: 1.7.0_71
    LWJGL_VERSION: 2.9.0
    GL_VERSION: 4.3.0
    GL_VENDOR: NVIDIA Corporation
    GL_RENDERER: GeForce GTX 560 Ti/PCIe/SSE2

    Thanks for any help in advance.

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    3,105
    The main thing to bear in mind about OpenGL's fixed-function lighting is that it calculates a colour for each vertex, and those colours are linearly interpolated across the polygon.

    How well this works depends upon the resolution of the geometry relative to the lighting, i.e. whether you have enough vertices to adequately sample the illumination.

    The number of cases where it works well In practice is rather low. Games almost (?) never use OpenGL's lighting. Early OpenGL-based games (e.g. GLQuake, Quake 2) used light maps, modern games use fragment shaders to perform lighting calculations per fragment (pixel).

  3. #3
    Junior Member Newbie
    Join Date
    Apr 2015
    Posts
    23
    Funny enough, I just found this out a few hours ago and have since been looking into GLSL - vertex and fragment shaders - and it doesn't seem too hard so I'll try that instead (and I can add more than 8 lights! awesome!). Thanks for pointing it out and the additional interesting info

    So as kind of a followup (that doesn't really fit here but you seem like you know a lot about GLSL so I will ask now ):

    I am currently setting everything up to transition from the old lighting models to GLSL's shaders. I am already wondering how to create (fast) cone spotlights (spotlights with a limited angle) in GLSL?
    Additionally, it would be awesome if you could tell me that in your opinion is the best way to render multiple lights (pass an array of lights and render it in one blend pass? multiple blend passes that blend together? - I don't know how to pass an array of lights to GLSL nor how to handle multiple lights at once).

    Thank you very much for your help

    EDIT:

    Also, how is it possible to selectively apply certain lights to certain textures? (For example I don't want GUI to be affected at all, and my lights have depth ranges (every texture in that range is affected - others aren't))

  4. #4
    Senior Member OpenGL Lord
    Join Date
    Mar 2015
    Posts
    6,675
    I am already wondering how to create (fast) cone spotlights (spotlights with a limited angle) in GLSL?
    Once upon a time, the answer would have been to use a projected texture or cubemap. On modern hardware however, in-shader computations are much faster than texture lookups.

    So just do the math yourself. Spotlight math is pretty simple; you fade out the light's intensity based on the result of a dot product between the direction from the point towards the light and the direction of the spotlight. OpenGL's fixed-function pipeline does exponential falloff, but you can use whatever makes your scene work.

    Additionally, it would be awesome if you could tell me that in your opinion is the best way to render multiple lights (pass an array of lights and render it in one blend pass? multiple blend passes that blend together?
    There really is no "best way", as each method has its own benefits and drawbacks. Deferred rendering is a solid solution to the problem, but it can be bandwidth intensive, and it makes multisample anti-aliasing quite expensive. There are variations on deferred rendering (light pre-pass, as explained there), which have different drawbacks. The single-light-per-pass approach can work, though it really benefits from a depth pre-pass (rendering just the depth of everything, so that only fragments that contribute to the result are executed).

    In your case, I'd just start with whatever works. As you start to understand the performance concerns your program will encounter, you'll start to see what the best solution for you is.

    I don't know how to pass an array of lights to GLSL
    The same way you pass an array of anything to GLSL.

    Normally, I would suggest a simple UBO, using std140 layout. However, I see that you're using LWJGL, which means Java. That makes it a bit more difficult to pass structured data via buffer objects. Not impossible, just a bit more difficult to work with than in C or C++, where you can just do some pointer casting and memory copies.

    So it would probably be easier to use an array of uniforms and call glProgramUniform (or glUniform if you want to do it old-school). Your data in GLSL would preferably be structured as an array of basic types:

    Code :
    #define MAX_NUM_LIGHTS 4
     
    uniform int numLights;
    uniform vec3 lightPositions[MAX_NUM_LIGHTS];
    uniform vec3 lightIntensities[MAX_NUM_LIGHTS];

    And in OpenGL, you would get the uniform locations for 'lightPositions' and 'lightIntensities', then call glProgramUniform3fv (or the LWJGL equivalent). This function can take an array of vec3's to upload.

    nor how to handle multiple lights at once
    Lighting is additive, so just take the sum of the result computed from each light.

  5. #5
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    3,105
    Quote Originally Posted by _1337_ View Post
    I am currently setting everything up to transition from the old lighting models to GLSL's shaders. I am already wondering how to create (fast) cone spotlights (spotlights with a limited angle) in GLSL?
    Subtract the surface position from the light position to get a direction, calculate the dot product between that and the light's direction to obtain the cosine of the angle between them. Clamp to the positive range (i.e. negative values become zero). Then you can either use a step or smoothstep function for a (relativelY) hard edge, or any other function for a smooth falloff.

    Quote Originally Posted by _1337_ View Post
    Additionally, it would be awesome if you could tell me that in your opinion is the best way to render multiple lights (pass an array of lights and render it in one blend pass? multiple blend passes that blend together?
    It depends. If you have a lot of overdraw, deferred rendering may be worthwhile (as it means that you only perform lighting calculations on visible surfaces, not on occluded surfaces). Additionally, if each light only affects a small portion of the scene, tiled rendering can reduce the amount of computation required (as you can completely ignore lights which don't affect the current tile).

    Quote Originally Posted by _1337_ View Post
    - I don't know how to pass an array of lights to GLSL
    Use a uniform buffer object to supply the data for an array of structures (similar to the definition of gl_LightSource in the compatibility profile, although you probably won't need as many fields).

    Quote Originally Posted by _1337_ View Post
    nor how to handle multiple lights at once).
    Just add together all of the contributions from the individual lights.

    Quote Originally Posted by _1337_ View Post
    Also, how is it possible to selectively apply certain lights to certain textures? (For example I don't want GUI to be affected at all, and my lights have depth ranges (every texture in that range is affected - others aren't))
    You'd normally draw the GUI in a separate draw call, so you can just change the array of light sources for the GUI (or use a different shader program altogether).

    Distance limits would typically be implemented using attenuation. To avoid a sudden cut-off, you can subtract a small "floor" value and clamp to positive, so lights are effectively cut off when the un-clamped value becomes negative.

    For culling, a simple option is to add an integer attribute containing a bitmask of the lights which affect a given surface.

    Beyond that, the almost limitless capabilities offered by shaders mean that lighting is now an incredibly complex subject. Simply reading all of the papers and articles which are being written on the subject would be a full-time job.

  6. #6
    Junior Member Newbie
    Join Date
    Apr 2015
    Posts
    23
    @AlfonseReinheart and @GClements, thank you both very much for your amazingly detailed responses, they really help me a lot. The only thing I still don't have any idea how to go about is the distance limit; I don't really understand your explanation. To explain my situation, it is a 2D project with perspective view for some visual effects (bumping certain parts of the screen in and out). The thing is, the "depth" is not the z coordinate (which would mean that it would be rendered in a different size), but rather an arbitrary value I added to all my game objects to render them in a particular order (to maintain using orthographic coordinates and controllable resize behaviour). So when I know have an array of lights passed to GLSL, how could I go about the depth ranges for lights? Like for example anything positive is foreground ("above" the main field of action where entities and terrain is), anything negative is background and depth 0 is the main field. When I only want objects of a certain depth to be affected by lights that contain that depth in their depthrange (if lightmindepth <= objectdepth <= lightmaxdepth)? Like, the lights are calculated once, right? Not for every object drawn (well in a certain way they are, but I don't know their depth anymore then or what they originally were) at least. Then there are partially transperent textures through which you could of course see some background light and so on. That still really confuses me, it would be awesome if could clear that up for me Thanks again, your help is awesome.

  7. #7
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    3,105
    If you want to take account of the depth in the lighting calculation, then the depth needs to be passed to the shader. If you're drawing all objects with a given depth in a separate pass, you can use a uniform variable. Otherwise it will need to be a vertex attribute.

  8. #8
    Junior Member Newbie
    Join Date
    Apr 2015
    Posts
    23
    Thanks for the quick and enlightening reply. I think I understand that now. So I either pass it as a vertex and draw it all in one go or I draw it sequentially grouped by depth so that I can pass it as a uniform variable. This may sound stupid, but is it somehow possible to pass the depth in the vertex while still keeping the original z-coordinate? Like, two depth coordinates in vertex (additionally to x and y)?

  9. #9
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    3,105
    Quote Originally Posted by _1337_ View Post
    is it somehow possible to pass the depth in the vertex while still keeping the original z-coordinate? Like, two depth coordinates in vertex (additionally to x and y)?
    You can pass many attributes for each vertex.

    You could pass the depth in the w coordinate of the position attribute, or you could add a separate attribute. Using a separate attribute has the advantage that it can be a different size (e.g. the depth could be an unsigned byte while the position uses 32-bit floats). Also, the depth attribute can be "flat"-qualified, meaning that the value is guaranteed to be constant for each triangle.

  10. #10
    Junior Member Newbie
    Join Date
    Apr 2015
    Posts
    23
    Ahhh. Thanks again. I think I know how to do it with the w-coordinate, but the seperate attribute seems to be a cleaner (and more flexible) solution.How is it possible to add a new attribute (and access it in GLSL)?

Page 1 of 5 12345 LastLast

Similar Threads

  1. Slipt edges as smooth transition between objects
    By Jamiro in forum OpenGL: Advanced Coding
    Replies: 4
    Last Post: 01-18-2018, 10:00 AM
  2. Edges are not smooth - GL_LINE_STRIP
    By Kevin Peter in forum OpenGL: Basic Coding
    Replies: 1
    Last Post: 03-13-2009, 05:32 PM
  3. Geforce cards: Precision issues at triangle edges
    By Jan in forum OpenGL: Advanced Coding
    Replies: 6
    Last Post: 01-13-2005, 11:05 AM
  4. Spotlights
    By in forum OpenGL: Basic Coding
    Replies: 0
    Last Post: 11-07-2002, 04:48 PM
  5. edges not smooth
    By guille in forum OpenGL: Basic Coding
    Replies: 4
    Last Post: 11-06-2001, 03:29 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Proudly hosted by Digital Ocean