Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm making a sky gradient in OpenGL by drawing with glColorPointer and glDrawArrays. I would like to be able to change the sky colour from morning to daytime to evening etc. I can either:

  • Make a number of sprites and fade them in with my framework
  • Somehow tween the color vector in openGL over time and use a single sprite

The second one seems like a more efficient option, but my framework doesn't pass the time delta into the draw method for me to decide how far I've progressed into fading.

Here's my current code:

glDisable(GL_BLEND);
glDisable(GL_DITHER);
glDisable(GL_FOG);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);

CGSize size = [[CCDirector sharedDirector] winSize];
float w = size.width;
float h = size.height;

const GLfloat vertices[] = {
    0, 0,
    w, 0,
    0, h/3,
    w, h/3,
    0, h*2/3,
    w, h*2/3,
    0, h,
    w, h,
};

const GLubyte colors[] = {
    254,255,134,255,
    254,255,134,255,
    230,157,0,255,
    230,157,0,255,
    230,60,0,255,
    230,60,0,255,
    167,0,86,255,
    167,0,86,255,
};

glVertexPointer(2, GL_FLOAT, 0, vertices);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
glEnableClientState(GL_COLOR_ARRAY);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);

glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

glEnable(GL_TEXTURE_2D);

Which gives me:

share|improve this question
    
"but my framework doesn't pass the time delta into the draw method" Then your framework is terrible and should be fixed and/or abandoned ASAP. If your drawing code has no way to get a time delta, then that's something that needs to be fixed. –  Nicol Bolas Jan 31 '12 at 7:41
2  
@Nicol I don't think I've ever used a framework that passed dT into the draw method. And you could just as easily encapsulate that functionality in a class in which draw method uses a variable that gets updated in its update method (which presumably has access to dT). –  Tetrad Jan 31 '12 at 7:49
3  
This doesn't really answer your question - but you may get better results by tweening Hue-Saturation-Lightness/Value instead of RGB. It should result in a seemingly more natural transition. Also, nothing is stopping you from calculating the time deltas yourself; or update the sky entity from the update function with the time of day. –  Jonathan Dickinson Jan 31 '12 at 8:22
1  
@NicolBolas: Excuse me, but why would you need the time delta in the drawing method? Isn't the time delta only interesting in the update-logic, f.e. to know how much to move the ball down the slope? –  Bobby Jan 31 '12 at 8:34
2  
@Bobby: It depends on what you mean by "the draw method". That is, what the main drawing function's responsibilities are. The OP, for example, wants his drawing function to perform animation on drawing parameters. Is that something he should compute outside of the draw function? It depends on how he wants to structure his code. If there were serious animation, then there would need to be a system to handle animation of all kinds, then feed those values into hooks to the rendering system. But again, it depends on what he wants. –  Nicol Bolas Jan 31 '12 at 16:10
show 4 more comments

1 Answer

up vote 3 down vote accepted

I fail to see what's the problem you're having. Update the time of day and tween the colors in the Update method (assuming it has access to the dt) and leave the Draw method only for rendering. I think that's the more logical solution. Also, encapsulate this in some sort of Sky class if you haven't done so already. So I'd definetly stick to the 2nd option. Something like:

class Sky
{
    void Update(float dt)
    {
        // Update timeOfDay based on dt
        // Update colors array based on timeOfDay
    }

    void Draw()
    {
        // Render sprite using current colors
    }

    float timeOfDay;
}

Edit

You wrote on the comments:

The gradient I have defined above is split into sections, but I could conceivably split them into less or more, meaning I would complicate going from 4 colours to 3 colours etc.

So that's where the real problem lies. You should have been more clear about it instead of giving focus to the dt issue. In that case, you could consider using a fragment shader solution, but I think that the first option will be simpler to implement.

In particular, I think it would be a good idea to start by encapsulating the vertex/color generation code in a method that given a simple array of colors, would return the vertex/color arrays required for calling glVertexPointer and glColorPointer. Then use this method to generate each of the gradient sprites, and finally, given the timeOfDay determine which two of these sprites should be interpolated and by what amount. Then draw them on top of each other and interpolate the alpha value so that there's a cross-fade between them.

The alternative that would only require one sprite would be to do the gradient on a fragment shader. The first implementation that comes to my mind would be to pass it two 1D textures where each pixel corresponds to one of the colors of the gradient, along with an interpolation value between 0 and 1 to decide how much to fade between texture A and B. Then just render a single quad, and use the information above to calculate the color at each fragment. I'm not sure but you may also need to pass it either the width of the textures or how many colors there are in each of them in order to calculate the correct texture coordinates from which you should sample. There are probably other solutions though.

share|improve this answer
    
Thanks David, I was thinking along the same line, but I'm still unsure how to easily set colours. The gradient I have defined above is split into sections, but I could conceivably split them into less or more, meaning I would complicate going from 4 colours to 3 colours etc. –  Aram Kocharyan Jan 31 '12 at 9:52
    
@AramKocharyan I see. Check my edit then. –  David Gouveia Jan 31 '12 at 11:08
    
Thanks for your in depth explanation! –  Aram Kocharyan Jan 31 '12 at 12:55
    
I figured I only need two "GradientFill" sprites and I can load the nextState texture and fade into the current state, then unload the old state and load the next etc. –  Aram Kocharyan Jan 31 '12 at 12:57
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.