Efficient reflections in Clutter/COGL? - c

I'm working on a program that uses Clutter (1.10) and COGL to render elements to the display.
I've created a set of ClutterTextures that I am rendering video to, and I'd like the video textures to have reflections.
The "standard" way to implement this seems to be a callback every time the texture is painted, with code similar to:
static void texture_paint_cb (ClutterActor *actor ) {
ClutterGeometry geom;
CoglHandle cmaterial;
CoglHandle ctexture;
gfloat squish = 1.5;
cogl_push_matrix ();
clutter_actor_get_allocation_geometry (actor, &geom);
guint8 opacity = clutter_actor_get_paint_opacity (actor);
opacity /= 2;
CoglTextureVertex vertices[] =
{
{ geom.width, geom.height, 0, 1, 1 },
{ 0, geom.height, 0, 0, 1 },
{ 0, geom.height*squish, 0, 0, 0 },
{ geom.width, geom.height*squish, 0, 1, 0 }
};
cogl_color_set_from_4ub (&vertices[0].color, opacity, opacity, opacity, opacity);
cogl_color_set_from_4ub (&vertices[1].color, opacity, opacity, opacity, opacity);
cogl_color_set_from_4ub (&vertices[2].color, 0, 0, 0, 0);
cogl_color_set_from_4ub (&vertices[3].color, 0, 0, 0, 0);
cmaterial = clutter_texture_get_cogl_material (CLUTTER_TEXTURE (actor));
ctexture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (actor));
cogl_material_set_layer (cmaterial, 0, ctexture);
cogl_set_source(cmaterial);
cogl_set_source_texture(ctexture);
cogl_polygon (vertices, G_N_ELEMENTS (vertices), TRUE);
cogl_pop_matrix ();
}
This is then hooked to the paint signal on the ClutterTexture. There's a similar bit of code here that does something similar. (Google cache, since the page has been down today)
The problem that I'm having is that the reflection effect is causing a performance hit - 5~7 fps is being lost when I enable it. Part of the problem is likely the low-power hardware I'm using (a Raspberry Pi).
I've managed to do something similar to what this code does, by setting up a clone of the texture and making it somewhat transparent. This causes no performance hit whatsoever. However, unlike the paint callback method, the reflection has hard edges and doesn't fade out.
I'd like to get a better looking reflection effect without the performance hit. I'm wondering if there's some way to get a similar effect that doesn't require so much work per paint... There are a bunch of other Clutter and COGL methods that manipulate materials, shaders, and so forth, but I have little to no OpenGL expertise so I don't have any idea if I could get something along those lines to do what I want, or even how to find examples of something similar I could work off of.
Is it possible to get a better looking, high performance reflection effect via Clutter/COGL?

Related

sdl2 flickering unless I don't use createrenderer

I have a somewhat basic rendering loop which blits a scaled image to the screen as fast as I can process the event loop. I created a minimal example that recreates the flickering on pastebin here.
If I don't use "SDL_CreateRenderer", and instead leave renderer to NULL, it works. I just can't clear the screen first. If I set the renderer, I get this crazy fast flickering.
// if I comment this out in my init_sdl(), no flickering...
renderer = SDL_CreateRenderer(window, -1, 0);
assert(renderer != NULL);
my draw function happens at the end of the event loop:
void draw()
{
SDL_SetRenderDrawColor(renderer, 255, 0, 128, 255);
SDL_RenderClear(renderer);
SDL_Rect dstrect = {
.x = 50,
.y = 50,
.h = 100,
.w = 100,
};
SDL_BlitScaled(img, NULL, screen, &dstrect);
SDL_UpdateWindowSurface(window);
SDL_RenderPresent(renderer);
}
I've seen this potential duplicate question, but the problem was that they had their RenderPresent in the wrong place. You can see I'm calling SDL_RenderPresent at the end of all drawing operations, which was my takeaway from that. It is still happening.
I'm using msys2 (mingw_x64), gcc, windows 10, SDL2.

Processing doesn't draw complete curves using while loop

I'm investigating possibilities that Processing gives regarding generative art, and I stumbled upon a problem:
I'd like to generate multiple Bezier curves using a while loop. However, the program skips parts of some curves, while others are drawn properly.
Here's a working example:
void setup() {
size(1000,500);
background(#ffffff);
}
float[] i_x = {1,1};
float[] i_y = {1,1};
void draw() {
while (i_y[0] < height)
{
bezier(0,i_y[0],100,height-100,width - 100,height-100,width, i_y[0]);
i_y[0] = i_y[0] * 1.1;
}
save("bezier.jpg");
}
And here is the output. As you can see, only few of the curves are drawn in their full shape.
Also, when I draw one of the 'broken' curves out of the loop, it works fine.
I'd appreciate any help. I'm having good time learning coding concepts with visual output that Processing provides.
It works as intended. Look what happens when you change the background color (great post btw, the working example made it good enough for me to want to debug it!):
If you're clever, you'll notice that the "inside" of the curve has a color. Except that for now it's white. That's why only the topmost are "invisible": you're drawing them one after the other, starting topmost, so every new curve eats the last one by painting over it, but only "inside the curve". See what happens when I apply some color to differentiate the fill and the background better:
Now that the problem is obvious, here's the answer: transparency.
while (y < height)
{
fill(0, 0, 0, 0); // this is the important line, you can keep your algo for the rest
bezier(0, y, offset, height-offset, width - offset, height-offset, width, y);
y *= 1.1;
}
Which gives us this result:
Have fun!

End of draw loop causing massive delay

I have multiple 'modes' which draw different things on the screen e.g. movement, inventory. When I switch between these, I am using a transition that fades black then fade back into the other mode.
The transition uses millis() and the time it started to determine how transparent to make a black rectangle that covers the screen.
However there is a massive delay at the end of the draw function which is disrupting this. The delay happens right after the mode that is being drawn behind the rectangle changes. It also only happens on the first transition made, not on subsequent ones.
What is causing the delay and how can I prevent it?
My code is very long and I have not been able to find what might be causing this. So I'm not sure exactly what code to post.
I've tried using processing's inbuilt debugger but the debugger doesn't pause millis() which makes it very unhelpful.
I've also tried adding several println() statements as timestamps but these only narrow the problem down to being between the end of draw() and the start of then next loop of draw()
// Transitions
if (p.transMode != ""){
if (timer == 0){
timer = millis();
} // If timer hasn't been started
ctime = millis() - timer; // current time
if (ctime < (transT*2/5)){
fill (0, 0, 0, map(ctime, 0, transT*2/5, 0, 255));
// Get darker
}
else if (ctime < transT/2){
p.transMode != p.mode){fill (0, 0, 0, 255);
p.mode = p.transMode;
// change mode in transition and move if able, fill black
}
else if (ctime < transT){
fill (0, 0, 0, map(ctime - transT/2, 0, transT/2, 255, 0));
// Get lighter
}
else { // If transition finished
timer = 0; // reset timer
p.transMode = ""; // turn off transition
fill(0, 0, 0, 0);
}
// draw transition rectangle
beginShape();
vertex(-100, -100, 200);
vertex(1100, -100, 200);
vertex(1100, 600, 200);
vertex(-100, 600, 200);
endShape();
}
Instead of fading back into the new mode it stays completely black for longer then suddenly cuts to the other mode (the timer doesn't let it enter the if statement that is making it fade back).

Use polygons as clickable zones, instead of rectangles

I'm creating a 2D game using the allegro library and I need to create polygonal territories on a map that the player can click on to move his units.
Am I forced to use some sort of point in polygon detection algorithm or is there a simpler solution using the polygon I drew already?
So far I managed to draw a polygon such as:
ALLEGRO_VERTEX v[] =
{
{ .x = 0, .y = 0, .z = 0, .color = al_map_rgb_f(1, 0, 0) },
{ .x = 0, .y = 48, .z = 0, .color = al_map_rgb_f(1, 0, 0) },
{ .x = 32, .y = 64, .z = 0, .color = al_map_rgb_f(1, 0, 0) },
{ .x = 80, .y = 32, .z = 0, .color = al_map_rgb_f(1, 0, 0) },
{ .x = 112, .y = 0, .z = 0, .color = al_map_rgb_f(1, 0, 0) }
};
al_draw_prim(v, NULL, NULL, 0, 5, ALLEGRO_PRIM_TRIANGLE_FAN);
EDIT: Ok I figured I can detect if the mouse is in a polygon using this algorithm still I feel this is not the right way to do this. I still need to call the function for every different polygon, that doesn't sound right.
You found an algorithm that does point-in-polygon for all your polygons and tells you which polygon the user clicked on. Good job you can use that. You wanted a built-in API call to do it and didn't get it. Since nobody else posted a contrary answer, I presume you won't. You should use what you've got.
I will now address why this should feel right rather than not feel right.
If the library itself had implemented it for you, it would still be constrained by the underlying OS primitives, which are in turn constrained by the algorithmic complexity of the problem, which is point-in-polygon per polygon. Thus, you may project all the polygons in your application, use one mouse hit box for the whole screen, and test them in turn. This is what the API would have had to do if there was an API for this.
I project a significant chance you coded it and found it too slow. An easy solution that almost always works is to do an axis-oriented bounding box test first, which is fast.
BugSquasher suggests an alternate solution. Render twice, with the second to an offscreen buffer with one color per polygon, and point-test the color. This also works, and is a good speedup if hit-testing is much more common than polygon moving. It does cost memory though.

Why doesn't this code draw a triangle?

I'm very new to OpenGL and I just wrote up a section of code using SDL 2 that to my knowledge should have drawn a triangle, but this code doesn't seem to work and so I am not done learning. I've got all the initialization code SDL 2 documentation says I need already written in, and the functions returned by dynamic loading ARE callable. When I execute this code instead of a triangle I get a black (but cleared) window. Why does this code not draw the triangle I want, and why is the window cleared to black by this code? I want to know the technical details behind mainly the first question so I can depend on it later.
(*main_context.glViewport)(0, 0, 100, 100);
(*main_context.glBegin)(GL_TRIANGLES);
(*main_context.glColor4d)(255, 255, 255, 255);
(*main_context.glVertex3d)(1, 1, -50);
(*main_context.glVertex3d)(1, 30, 1);
(*main_context.glVertex3d)(30, 1, 1);
(*main_context.glEnd)();
(*main_context.glFinish)();
(*main_context.glFlush)();
SDL_GL_SwapWindow(window);
Update:
I've revised my code to include different coordinates and I got the triangle to draw, but I cannot get it to draw when farther away. Why is that?
(*main_context.glVertex3d)(2, -1, 1); /* Works. */
(*main_context.glVertex3d)(2, -1, 3); /* Doesn't work. */
Unless you are setting up a projection and/or modelview matrix elsewhere in your code, it's using the default (identity matrix) transform, which is an orthographic projection with (-1, -1) at the bottom left and (1, 1) at the top right. glViewport only changes the portion of the default framebuffer being rendered to, it has no bearing on the projection whatsoever.
With an orthographic projection, the Z coordinate does not affect the screen-space position of a point, except that points outside the Z clipping planes will not be rendered. In this case, that's everything outside of -1 <= z <= 1. Given that one of your points is (1, 1, -50), this seems to be your problem.

Resources