mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-19 08:11:16 +00:00
[661/906] glass: port to non-glew + shader matrices
This commit is contained in:
parent
0497326a43
commit
753dfca775
2 changed files with 174 additions and 95 deletions
|
@ -70,34 +70,80 @@ static gboolean gst_gl_filter_glass_filter_texture (GstGLFilter * filter,
|
|||
static void gst_gl_filter_glass_draw_background_gradient ();
|
||||
static void gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter,
|
||||
gint width, gint height, guint texture, gfloat center_x, gfloat center_y,
|
||||
gfloat start_alpha, gfloat stop_alpha, gboolean reversed);
|
||||
gfloat start_alpha, gfloat stop_alpha, gboolean reversed, gfloat rotation);
|
||||
|
||||
static void gst_gl_filter_glass_callback (gint width, gint height,
|
||||
guint texture, gpointer stuff);
|
||||
static void gst_gl_filter_glass_callback (gpointer stuff);
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
static const gchar *glass_fragment_source =
|
||||
"#extension GL_ARB_texture_rectangle : enable\n"
|
||||
"uniform sampler2DRect tex;"
|
||||
"uniform float width, height;"
|
||||
"void main () {"
|
||||
" float p = 0.0525;"
|
||||
" float L1 = p*width;"
|
||||
" float L2 = width - L1;"
|
||||
" float L3 = height - L1;"
|
||||
" float w = 1.0;"
|
||||
" float r = L1;"
|
||||
" if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y < L1)"
|
||||
" r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L1) * (gl_TexCoord[0].y - L1) );"
|
||||
" else if (gl_TexCoord[0].x > L2 && gl_TexCoord[0].y < L1)"
|
||||
" r = sqrt( (gl_TexCoord[0].x - L2) * (gl_TexCoord[0].x - L2) + (gl_TexCoord[0].y - L1) * (gl_TexCoord[0].y - L1) );"
|
||||
" else if (gl_TexCoord[0].x > L2 && gl_TexCoord[0].y > L3)"
|
||||
" r = sqrt( (gl_TexCoord[0].x - L2) * (gl_TexCoord[0].x - L2) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );"
|
||||
" else if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y > L3)"
|
||||
" r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );"
|
||||
" if (r > L1)"
|
||||
" w = 0.0;"
|
||||
" vec4 color = texture2DRect (tex, gl_TexCoord[0].st);"
|
||||
" gl_FragColor = vec4(color.rgb, gl_Color.a * w);" "}";
|
||||
"uniform sampler2DRect tex;\n"
|
||||
"uniform float width, height;\n"
|
||||
"varying float alpha;\n"
|
||||
"void main () {\n"
|
||||
" float p = 0.0525;\n"
|
||||
" float L1 = p*width;\n"
|
||||
" float L2 = width - L1;\n"
|
||||
" float L3 = height - L1;\n"
|
||||
" float w = 1.0;\n"
|
||||
" float r = L1;\n"
|
||||
" if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y < L1)\n"
|
||||
" r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L1) * (gl_TexCoord[0].y - L1) );\n"
|
||||
" else if (gl_TexCoord[0].x > L2 && gl_TexCoord[0].y < L1)\n"
|
||||
" r = sqrt( (gl_TexCoord[0].x - L2) * (gl_TexCoord[0].x - L2) + (gl_TexCoord[0].y - L1) * (gl_TexCoord[0].y - L1) );\n"
|
||||
" else if (gl_TexCoord[0].x > L2 && gl_TexCoord[0].y > L3)\n"
|
||||
" r = sqrt( (gl_TexCoord[0].x - L2) * (gl_TexCoord[0].x - L2) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );\n"
|
||||
" else if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y > L3)\n"
|
||||
" r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );\n"
|
||||
" if (r > L1)\n"
|
||||
" w = 0.0;\n"
|
||||
" vec4 color = texture2DRect (tex, gl_TexCoord[0].st);\n"
|
||||
" gl_FragColor = vec4(color.rgb, alpha * w);\n"
|
||||
"}\n";
|
||||
|
||||
static const gchar *glass_vertex_source =
|
||||
"uniform float yrot;\n"
|
||||
"uniform float width, height;\n"
|
||||
"const float fovy = 80.0;\n"
|
||||
"const float znear = 1.0;\n"
|
||||
"const float zfar = 5000.0;\n"
|
||||
"varying float alpha;\n"
|
||||
"void main () {\n"
|
||||
" float f = 1.0/(tan(radians(fovy/2.0)));\n"
|
||||
" float rot = radians (yrot);\n"
|
||||
" float aspect = width/height;\n"
|
||||
" // replacement for gluPerspective\n"
|
||||
" mat4 perspective = mat4 (\n"
|
||||
" f/aspect, 0.0, 0.0, 0.0,\n"
|
||||
" 0.0, f, 0.0, 0.0,\n"
|
||||
" 0.0, 0.0, (znear+zfar)/(znear-zfar), 2.0*znear*zfar/(znear-zfar),\n"
|
||||
" 0.0, 0.0, -1.0, 0.0 );\n"
|
||||
" mat4 trans = mat4 (\n"
|
||||
" 1.0, 0.0, 0.0, 0.0,\n"
|
||||
" 0.0, 1.0, 0.0, 0.0,\n"
|
||||
" 0.0, 0.0, 1.0, -3.0,\n"
|
||||
" 0.0, 0.0, 0.0, 1.0 );\n"
|
||||
" mat4 rotation = mat4 (\n"
|
||||
" cos(rot), 0.0, sin(rot), 0.0,\n"
|
||||
" 0.0, 1.0, 0.0, 0.0,\n"
|
||||
" -sin(rot), 0.0, cos(rot), 0.0,\n"
|
||||
" 0.0, 0.0, 0.0, 1.0 );\n"
|
||||
" gl_Position = trans * perspective * rotation * gl_ModelViewProjectionMatrix * gl_Vertex;\n"
|
||||
" gl_TexCoord[0] = gl_MultiTexCoord0;\n"
|
||||
" alpha = gl_Color.a;\n"
|
||||
"}\n";
|
||||
|
||||
static const gchar * passthrough_vertex =
|
||||
"void main () {\n"
|
||||
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
|
||||
" gl_FrontColor = gl_Color;\n"
|
||||
"}\n";
|
||||
|
||||
static const gchar * passthrough_fragment =
|
||||
"void main () {\n"
|
||||
" gl_FragColor = gl_Color;\n"
|
||||
"}\n";
|
||||
/* *INDENT-ON* */
|
||||
|
||||
static void
|
||||
gst_gl_filter_glass_class_init (GstGLFilterGlassClass * klass)
|
||||
|
@ -135,6 +181,7 @@ gst_gl_filter_glass_reset (GstGLFilter * filter)
|
|||
|
||||
//blocking call, wait the opengl thread has destroyed the shader
|
||||
gst_gl_display_del_shader (filter->display, glass_filter->shader);
|
||||
gst_gl_display_del_shader (filter->display, glass_filter->passthrough_shader);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -166,30 +213,34 @@ gst_gl_filter_glass_get_property (GObject * object, guint prop_id,
|
|||
static gboolean
|
||||
gst_gl_filter_glass_init_shader (GstGLFilter * filter)
|
||||
{
|
||||
gboolean ret;
|
||||
GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter);
|
||||
|
||||
//blocking call, wait the opengl thread has compiled the shader
|
||||
return gst_gl_display_gen_shader (filter->display, 0, glass_fragment_source,
|
||||
&glass_filter->shader);
|
||||
ret =
|
||||
gst_gl_display_gen_shader (filter->display, glass_vertex_source,
|
||||
glass_fragment_source, &glass_filter->shader);
|
||||
if (ret)
|
||||
ret =
|
||||
gst_gl_display_gen_shader (filter->display, passthrough_vertex,
|
||||
passthrough_fragment, &glass_filter->passthrough_shader);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_gl_filter_glass_filter_texture (GstGLFilter * filter, guint in_tex,
|
||||
guint out_tex)
|
||||
{
|
||||
gpointer glass_filter = GST_GL_FILTER_GLASS (filter);
|
||||
GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter);
|
||||
glass_filter->in_tex = in_tex;
|
||||
|
||||
//blocking call, use a FBO
|
||||
gst_gl_display_use_fbo (filter->display,
|
||||
gst_gl_display_use_fbo_v2 (filter->display,
|
||||
GST_VIDEO_INFO_WIDTH (&filter->out_info),
|
||||
GST_VIDEO_INFO_HEIGHT (&filter->out_info),
|
||||
filter->fbo, filter->depthbuffer, out_tex,
|
||||
gst_gl_filter_glass_callback,
|
||||
GST_VIDEO_INFO_WIDTH (&filter->in_info),
|
||||
GST_VIDEO_INFO_HEIGHT (&filter->in_info),
|
||||
in_tex, 80, (gdouble) GST_VIDEO_INFO_WIDTH (&filter->out_info) /
|
||||
(gdouble) GST_VIDEO_INFO_HEIGHT (&filter->out_info), 1.0, 5000.0,
|
||||
GST_GL_DISPLAY_PROJECTION_PERSPECTIVE, (gpointer) glass_filter);
|
||||
gst_gl_filter_glass_callback, (gpointer) glass_filter);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -204,92 +255,113 @@ get_time (void)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_gl_filter_glass_draw_background_gradient ()
|
||||
gst_gl_filter_glass_draw_background_gradient (GstGLFilterGlass * glass)
|
||||
{
|
||||
glMatrixMode (GL_PROJECTION);
|
||||
GstGLFilter *filter = GST_GL_FILTER (glass);
|
||||
GstGLFuncs *gl = filter->display->gl_vtable;
|
||||
|
||||
glPushMatrix ();
|
||||
glLoadIdentity ();
|
||||
glOrtho (-100, 100, -100, 100, -1000.0, 1000.0);
|
||||
/* *INDENT-OFF* */
|
||||
gfloat mesh[] = {
|
||||
/* | Vertex | Color | */
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
|
||||
1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
|
||||
1.0f, 0.8f, 0.0f, 0.0f, 0.0f, 0.2f, 1.0f,
|
||||
-1.0f, 0.8f, 0.0f, 0.0f, 0.0f, 0.2f, 1.0f,
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.2f, 1.0f,
|
||||
1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.2f, 1.0f,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
glBegin (GL_QUADS);
|
||||
GLushort indices[] = {
|
||||
0, 1, 2,
|
||||
0, 2, 3,
|
||||
2, 3, 4,
|
||||
2, 4, 5
|
||||
};
|
||||
|
||||
glColor4f (0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glVertex2f (-100.0f, -100.0f);
|
||||
glVertex2f (100.0f, -100.0f);
|
||||
gl->ClientActiveTexture (GL_TEXTURE0);
|
||||
gl->EnableClientState (GL_VERTEX_ARRAY);
|
||||
gl->EnableClientState (GL_COLOR_ARRAY);
|
||||
|
||||
glColor4f (0.0f, 0.0f, 0.2f, 1.0f);
|
||||
glVertex2f (100.0f, 80.0f);
|
||||
glVertex2f (-100.0f, 80.0f);
|
||||
gl->VertexPointer (3, GL_FLOAT, 7 * sizeof (gfloat), mesh);
|
||||
gl->ColorPointer (4, GL_FLOAT, 7 * sizeof (gfloat), &mesh[3]);
|
||||
|
||||
glVertex2f (100.0f, 80.0f);
|
||||
glVertex2f (-100.0f, 80.0f);
|
||||
gl->DrawElements (GL_TRIANGLES, 12, GL_UNSIGNED_SHORT, indices);
|
||||
|
||||
glVertex2f (-100.0f, 100.0f);
|
||||
glVertex2f (100.0f, 100.0f);
|
||||
|
||||
glEnd ();
|
||||
glPopMatrix ();
|
||||
|
||||
glMatrixMode (GL_MODELVIEW);
|
||||
gl->DisableClientState (GL_VERTEX_ARRAY);
|
||||
gl->DisableClientState (GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter,
|
||||
gint width, gint height, guint texture,
|
||||
gfloat center_x, gfloat center_y,
|
||||
gfloat start_alpha, gfloat stop_alpha, gboolean reversed)
|
||||
gfloat start_alpha, gfloat stop_alpha, gboolean reversed, gfloat rotation)
|
||||
{
|
||||
GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter);
|
||||
GstGLFuncs *gl = filter->display->gl_vtable;
|
||||
|
||||
gfloat topy;
|
||||
gfloat bottomy;
|
||||
if (reversed) {
|
||||
topy = center_y - 1.0f;
|
||||
bottomy = center_y + 1.0f;
|
||||
} else {
|
||||
topy = center_y + 1.0f;
|
||||
bottomy = center_y - 1.0f;
|
||||
}
|
||||
gfloat w = (gfloat) width;
|
||||
gfloat h = (gfloat) height;
|
||||
gfloat topy = reversed ? center_y - 1.0f : center_y + 1.0f;
|
||||
gfloat bottomy = reversed ? center_y + 1.0f : center_y - 1.0f;
|
||||
|
||||
gst_gl_shader_use (glass_filter->shader);
|
||||
/* *INDENT-OFF* */
|
||||
gfloat mesh[] = {
|
||||
/*| Vertex |TexCoord0| Colour |*/
|
||||
center_x-1.6, topy, 0.0, 0.0, h, 1.0, 1.0, 1.0, start_alpha,
|
||||
center_x+1.6, topy, 0.0, w, h, 1.0, 1.0, 1.0, start_alpha,
|
||||
center_x+1.6, bottomy, 0.0, w, 0.0, 1.0, 1.0, 1.0, stop_alpha,
|
||||
center_x-1.6, bottomy, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, stop_alpha,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
glActiveTextureARB (GL_TEXTURE0_ARB);
|
||||
glEnable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
|
||||
glDisable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
GLushort indices[] = {
|
||||
0, 1, 2,
|
||||
0, 2, 3
|
||||
};
|
||||
|
||||
gl->ActiveTexture (GL_TEXTURE0);
|
||||
gl->Enable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
|
||||
gl->Disable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
|
||||
gst_gl_shader_set_uniform_1i (glass_filter->shader, "tex", 0);
|
||||
gst_gl_shader_set_uniform_1f (glass_filter->shader, "width", (gfloat) width);
|
||||
gst_gl_shader_set_uniform_1f (glass_filter->shader, "height",
|
||||
(gfloat) height);
|
||||
gst_gl_shader_set_uniform_1f (glass_filter->shader, "yrot", rotation);
|
||||
|
||||
glBegin (GL_QUADS);
|
||||
glColor4f (1.0f, 1.0f, 1.0f, start_alpha);
|
||||
glTexCoord2i (0, height);
|
||||
glVertex2f (center_x - 1.6f, topy);
|
||||
glTexCoord2i (width, height);
|
||||
glVertex2f (center_x + 1.6f, topy);
|
||||
gl->ClientActiveTexture (GL_TEXTURE0);
|
||||
gl->EnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
gl->EnableClientState (GL_VERTEX_ARRAY);
|
||||
gl->EnableClientState (GL_COLOR_ARRAY);
|
||||
|
||||
glColor4f (1.0, 1.0, 1.0, stop_alpha);
|
||||
glTexCoord2i (width, 0);
|
||||
glVertex2f (center_x + 1.6f, bottomy);
|
||||
glTexCoord2i (0, 0);
|
||||
glVertex2f (center_x - 1.6f, bottomy);
|
||||
glEnd ();
|
||||
gl->VertexPointer (3, GL_FLOAT, 9 * sizeof (gfloat), mesh);
|
||||
gl->TexCoordPointer (2, GL_FLOAT, 9 * sizeof (gfloat), &mesh[3]);
|
||||
gl->ColorPointer (4, GL_FLOAT, 9 * sizeof (gfloat), &mesh[5]);
|
||||
|
||||
gst_gl_shader_use (0);
|
||||
gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
||||
|
||||
gl->DisableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
gl->DisableClientState (GL_VERTEX_ARRAY);
|
||||
gl->DisableClientState (GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
//opengl scene, params: input texture (not the output filter->texture)
|
||||
static void
|
||||
gst_gl_filter_glass_callback (gint width, gint height, guint texture,
|
||||
gpointer stuff)
|
||||
gst_gl_filter_glass_callback (gpointer stuff)
|
||||
{
|
||||
static gint64 start_time = 0;
|
||||
gfloat rotation;
|
||||
|
||||
GstGLFilter *filter = GST_GL_FILTER (stuff);
|
||||
GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (stuff);
|
||||
GstGLFuncs *gl = filter->display->gl_vtable;
|
||||
|
||||
gint width = GST_VIDEO_INFO_WIDTH (&filter->out_info);
|
||||
gint height = GST_VIDEO_INFO_HEIGHT (&filter->out_info);
|
||||
guint texture = glass_filter->in_tex;
|
||||
|
||||
if (start_time == 0)
|
||||
start_time = get_time ();
|
||||
|
@ -303,28 +375,33 @@ gst_gl_filter_glass_callback (gint width, gint height, guint texture,
|
|||
}
|
||||
}
|
||||
|
||||
glTranslatef (0.0f, 2.0f, -3.0f);
|
||||
|
||||
gst_gl_filter_glass_draw_background_gradient ();
|
||||
gst_gl_shader_use (glass_filter->passthrough_shader);
|
||||
|
||||
gst_gl_filter_glass_draw_background_gradient (glass_filter);
|
||||
|
||||
//Rotation
|
||||
if (start_time != 0) {
|
||||
gint64 time_passed = get_time () - start_time;
|
||||
glRotated (sin (time_passed / 1200000.0) * 45.0, 0.0, 1.0, 0.0);
|
||||
rotation = sin (time_passed / 1200000.0) * 45.0f;
|
||||
} else {
|
||||
rotation = 0.0f;
|
||||
}
|
||||
|
||||
glEnable (GL_BLEND);
|
||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
gl->Enable (GL_BLEND);
|
||||
gl->BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
gst_gl_shader_use (glass_filter->shader);
|
||||
|
||||
//Reflection
|
||||
gst_gl_filter_glass_draw_video_plane (filter, width, height, texture,
|
||||
0.0f, 0.0f, 0.3f, 0.0f, TRUE);
|
||||
0.0f, 2.0f, 0.3f, 0.0f, TRUE, rotation);
|
||||
|
||||
//Main video
|
||||
gst_gl_filter_glass_draw_video_plane (filter, width, height, texture,
|
||||
0.0f, -2.0f, 1.0f, 1.0f, FALSE);
|
||||
0.0f, 0.0f, 1.0f, 1.0f, FALSE, rotation);
|
||||
|
||||
glDisable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
glDisable (GL_BLEND);
|
||||
gst_gl_display_clear_shader (filter->display);
|
||||
|
||||
gl->Disable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
gl->Disable (GL_BLEND);
|
||||
}
|
||||
|
|
|
@ -38,8 +38,10 @@ typedef struct _GstGLFilterGlassClass GstGLFilterGlassClass;
|
|||
struct _GstGLFilterGlass
|
||||
{
|
||||
GstGLFilter filter;
|
||||
GstGLShader *passthrough_shader;
|
||||
GstGLShader *shader;
|
||||
gint64 timestamp;
|
||||
guint in_tex;
|
||||
};
|
||||
|
||||
struct _GstGLFilterGlassClass
|
||||
|
|
Loading…
Reference in a new issue