1. Anders Ruud
  2. love
  3. Issues

Issues

Issue #403 resolved

Per-vertex colors (with interpolation) for lines and polygons

xgoff
created an issue

It would be nice if love.graphics.polygon and love.graphics.line could have per-vertex colors, as having interpolated vertex colors is quite useful, especially with the resolution independence, performance, and flexibility you get over using an image. Also, blending looks nice.

This functionality would be available for the table versions of both functions, where they would take an additional (optional) table parameter. This table must be a multiple of 4 in length, as it would always contain RGBA quadruplets. eg:

{{{

!lua

love.graphics.polygon("fill", { 0, 0; 0, 32; 32, 32; 32, 0 }, { 255, 255, 255, 255; 255, 0, 0, 255; 0, 255, 0, 255; 0, 0, 255, 255 } )

love.graphics.line( { 0, 0; 0, 32; 32, 32 }, { 0, 0, 0, 0; 255, 255, 255, 255; 0, 0, 0, 0 } ) }}}

I'm not quite sure what the behavior should be if there are not enough vertex colors for all specified vertices. A few possibilities: Error Use the last specified vertex color * Fall back to the current color set by the last setColor

As the other shapes are reproducible with these functions, just these two should be sufficient.

Arguably this brings up whether there should be some way of specifying texture coordinates as well, along with a function to draw a textured polygon. Ideally LOVE would provide functions for working with VAs/VBOs directly but maybe that's outside the scope?

Comments (15)

  1. xgoff reporter

    out of boredom i tried implementing it myself but didn't spend a whole lot of effort trying to make it nice. didn't test it a whole lot either, but it works ok from the minimal testing i did give it (which didn't include fragment shaders).

    not a c++ programmer btw. some of the function argument additions aren't really consistent on top of that. if it leaks or crashes then oops! assuming the patch even applies that is

    anyway vertex colors are pretty awesome otherwise

  2. Matthias Richter
    • changed status to open

    I'd like to have something like that too, as well as per-vertex texture coordinates (which would allow for nice pixel effects). The problem is the API. Do you see a way to make it ... lövelier?

  3. xgoff reporter

    i wonder if something like a love.polygon module could work. it'd basically be a vbo-ized version of love.graphics. i imagine you could create Vertex and Line objects, which you could combine into more complex Shapes (which could probably take other Shapes as well). in effect you could end up with a huge, complex object that could be efficiently drawn in a single call (probably through love.graphics.polygon)

    position, color, and texcoord info would be provided with the Vertex creating function

    idk, this would probably take quite a bit of planning to work out

  4. Jonathan Brodsky

    +1 this issue. The api that would take a vertex object containing position, color, and texture uv seems good to me. This would also be subject to setting draw type though (triangle strip, triangle fan, etc), and explaining the complexities of degenerate triangles seems nutty.

    It would be nice to basically have exposed vbos though.

  5. xgoff reporter

    i'm working on a prototype implementation of this on and off. currently it's more or less a superset of spritebatch (in terms of functionality... in fact i've called it "pointbatch"). specifically, you add points (which contain position, colors, and texcoords) individually. you get back an index you can use in a separate method to set the index buffer data.

    for example, a crappy triangle:

    ----- love.load
    -- newPointBatch(image, maxpoints)
    pb = love.graphics.newPointBatch(nil, 3) -- nil for no image
    
    -- add(x, y, r, g, b, a, s, t)
    local ids = { 
        pb:add(100, 200, 255, 0, 0, 255, 0, 0),
        pb:add(200, 200, 0, 255, 0, 255, 0, 0),
        pb:add(150, 100, 0, 0, 255, 255, 0, 0),
    }
    
    -- addIndices(id1, ...)
    pb:addIndices(ids) -- also accepts individual values
    
    ----- love.draw
    -- pointbatch(mode, p, x, y, r, sx, sy, ox, oy, kx, ky)
    love.graphics.pointbatch("fill", pb, 0, 0) -- love.graphics.draw(pb, 0, 0) would be equivalent
    
    -- fun fact: i didn't even bother testing that
    

    additionally, there are methods to allow you to add points for the basic shapes like rectanges etc. these will also add indices for you, and return the id of the first index. oh and you can add an existing Quad, SpriteBatch, or PointBatch to a PointBatch as well (or more specifically, their points and shapes)

    still subject to change though. trying to get a decent api out of this is difficult:

    • currently it draws with GL_TRIANGLES. i'm not sure if there's really much point for eg TRIANGLE_STRIP etc since they'd complicate things even more
    • not sure how to handle line mode; indices meant for filled mode won't work directly with it. not to mention, should it use GL_LINES, GL_LINE_STRIP, or GL_LINE_LOOP?
    • i'm still not sure whether returned indices should be numbers or userdata. currently it uses numbers, but userdata would be nice since they could represent sets of indices (for shapes), and would make it easier to implement methods which would make it possible to move shapes around without potentially jacking up the index order in amusing ways. on the other hand, that's more crap for the gc to deal with, especially for individual points

    so yeah, slow going to say the least

  6. kikito

    The problem is the API. Do you see a way to make it ... lövelier?

    I've been thinking about this for a while. I think a lövelier way to do it would be to split things into two.

    New function:

    love.graphics.setPattern(image, ox, oy, sx, sy, r)
    -- sets the currently used texture pattern
    -- ox, oy: displacement from origin (default: 0, 0)
    -- sx, sy: scale (default: 1, 1)
    -- r: rotation in radians (default: 0)
    

    New drawmode: "pattern" (In addition to "line" and "fill"). It draws the chosen primitive filling it up with the currently selected texture.

    Examples:

    love.graphics.rectangle("pattern", 10, 10, 100, 100)
    love.graphics.circle("pattern", 200, 200, 30)
    love.graphics.polygon("pattern", 10, 10, 40, 40, 40, 10)
    

    Notes:

    • I think specifying colors/different textures per vertex is overkill. One texture/color per primitive is a good compromise between functionality and ease of use IMHO.
    • I'm no OpenGL expert. If someone knows a better set of parameters for love.graphics.setPattern, please comment.
    • Ox and oy are relative to the "origin of coordinates" of each primitive: The upper-left corner in rectangles, the center in circles, and the first vertex on polygons.
    • The "pattern" name is only an example. "texture" would probably do as well (love.graphics.setTexture + "texture" drawing mode)
    • If both a color and a pattern are set, then the pattern should be "tinted", including the alpha. This way we could create transparent textured primitives.
    • I think lines should not be textured. If this is needed, rotated rectangles can be used to that effect.
  7. xgoff reporter

    kikito

    that would be nice as a new mode for simple primitives, but for more complex texture mapping, you're going to want more than just a simple cookie-cutter out of a texture. also, the lack of control over triangulation is going to hurt for love.graphics.polygon (this alone pretty much forced me to expose raw vertex indices in my implementation).

    for example, you can see triangulation differences when using vertex colors: http://i.imgur.com/JQLbi.png

    fortunately that doesn't show up with textures, but concave shapes are still going to be a pain.

    I think specifying colors/different textures per vertex is overkill. One texture/color per primitive is a good compromise between functionality and ease of use IMHO.

    just one texture, actually. i disagree about per-vertex colors/texcoords though, that's pretty useful (particle effects, trails, more complicated fading shapes, etc).

    a nice thing about my proposal is that it just extends the current spritebatch functionality; in theory, the internal implementation of spritebatches would actually use this instead of their current system.

  8. jimknopf

    Have to agree with xgoff here. I am fairly new to love2d, so I do not know much about the design philosophies behind the project.

    However, from my point of view the lack of an API allowing the definition of arbitrary meshes and texture / color maps is THE main drawback of loved2d 0.8.

    One strength of love2d is how simple it is to set up a multi pass rendering system and to load shaders. All while being (appearing to be?) a very lightweight approach and being efficient (use Lua to set up the rendering system, let the GPU do the work). I see no reason why loved2d should not be able to be used for projects such as the game Limbo, well, except THIS missing API.

  9. kikito

    xgoff

    The "cookie butter" approach has been talked about a lot of times in the LÖVE forums. The "complex texture mapping" you are proposing, has not.

    If you can think of a way of adding it to the API without adding complexity, I'm all for it. But right now, I can't think of a way to do that, so I'm against doing the changes you propose; we should not increase the complexity for everyone to catter for the needs of a few.

    Michael Knopf

    IMHO LÖVE's philosophy can be expressed as follows: ease of use comes first. Then flexibility, and speed on the last position. You will not see it topping any efficiency benchmark, and there are some things that you just can't do with it. But its interface is one of the best ones out there (for the things it can do). Most of its userbase seems happy with this.

    In other words: LÖVE "hides" OpenGL on purpose. So far, this seems what the community wants.

    I think adding the functionality you mentioned would make LÖVE a bit too much "OpenGL with a Lua API". That's not at all what the framework is about.

    Big disclaimer: All of the above is IMHO. I'm not part of the core developers, but I've been around in the forums for a while.

  10. jimknopf

    kikito

    I see your point that LÖVE hides OpenGL on purpose. Never thought of it that way, although it is kind of obvious by hindsight.

    What irritates me in this context is the support for fragment shaders. They are not called that way, but nevertheless they do expose GLSL. Sure, you do not have to use them or know GLSL to use LÖVE, but neither would you need to use the proposed API or know what VBOs etc. are. However, having the option to use and in particular combine both could proof to be a very powerful tool.

    However, I guess the forum is a better place to discuss these matters.

    One last remark: I did not want to imply that code written for LÖVE itself is particularly efficient. In my (admittedly limited) experience, LÖVE simply does a good job in converting high level code such as combining multiple canvas objects, blending modes and pixel effects, which all can be done in a few easy to read lines, into fast OpenGL code.

  11. Alex Szpakowski

    Implemented for polygons via Geometry. Just use a 1x1 white pixel as an image if you don't want a 'real' texture.

    Feel free to create a new issue for per-vertex colors for line primitives.

  12. Log in to comment