[661/906] glass: port to non-glew + shader matrices

This commit is contained in:
Matthew Waters 2013-01-31 23:43:52 +11:00
parent 0497326a43
commit 753dfca775
2 changed files with 174 additions and 95 deletions

View file

@ -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_background_gradient ();
static void gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter, static void gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter,
gint width, gint height, guint texture, gfloat center_x, gfloat center_y, 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, static void gst_gl_filter_glass_callback (gpointer stuff);
guint texture, gpointer stuff);
/* *INDENT-OFF* */
static const gchar *glass_fragment_source = static const gchar *glass_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;\n"
"uniform float width, height;" "uniform float width, height;\n"
"void main () {" "varying float alpha;\n"
" float p = 0.0525;" "void main () {\n"
" float L1 = p*width;" " float p = 0.0525;\n"
" float L2 = width - L1;" " float L1 = p*width;\n"
" float L3 = height - L1;" " float L2 = width - L1;\n"
" float w = 1.0;" " float L3 = height - L1;\n"
" float r = L1;" " float w = 1.0;\n"
" if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y < L1)" " float r = L1;\n"
" r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L1) * (gl_TexCoord[0].y - L1) );" " if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y < L1)\n"
" else if (gl_TexCoord[0].x > L2 && 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) );\n"
" 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 < L1)\n"
" 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 - L1) * (gl_TexCoord[0].y - L1) );\n"
" 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 > L2 && gl_TexCoord[0].y > L3)\n"
" else if (gl_TexCoord[0].x < L1 && 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) );\n"
" r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );" " else if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y > L3)\n"
" if (r > L1)" " r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );\n"
" w = 0.0;" " if (r > L1)\n"
" vec4 color = texture2DRect (tex, gl_TexCoord[0].st);" " w = 0.0;\n"
" gl_FragColor = vec4(color.rgb, gl_Color.a * w);" "}"; " 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 static void
gst_gl_filter_glass_class_init (GstGLFilterGlassClass * klass) 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 //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->shader);
gst_gl_display_del_shader (filter->display, glass_filter->passthrough_shader);
} }
static void static void
@ -166,30 +213,34 @@ gst_gl_filter_glass_get_property (GObject * object, guint prop_id,
static gboolean static gboolean
gst_gl_filter_glass_init_shader (GstGLFilter * filter) gst_gl_filter_glass_init_shader (GstGLFilter * filter)
{ {
gboolean ret;
GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter); GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter);
//blocking call, wait the opengl thread has compiled the shader //blocking call, wait the opengl thread has compiled the shader
return gst_gl_display_gen_shader (filter->display, 0, glass_fragment_source, ret =
&glass_filter->shader); 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 static gboolean
gst_gl_filter_glass_filter_texture (GstGLFilter * filter, guint in_tex, gst_gl_filter_glass_filter_texture (GstGLFilter * filter, guint in_tex,
guint out_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 //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_WIDTH (&filter->out_info),
GST_VIDEO_INFO_HEIGHT (&filter->out_info), GST_VIDEO_INFO_HEIGHT (&filter->out_info),
filter->fbo, filter->depthbuffer, out_tex, filter->fbo, filter->depthbuffer, out_tex,
gst_gl_filter_glass_callback, gst_gl_filter_glass_callback, (gpointer) glass_filter);
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);
return TRUE; return TRUE;
} }
@ -204,92 +255,113 @@ get_time (void)
} }
static 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 (); /* *INDENT-OFF* */
glLoadIdentity (); gfloat mesh[] = {
glOrtho (-100, 100, -100, 100, -1000.0, 1000.0); /* | 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); gl->ClientActiveTexture (GL_TEXTURE0);
glVertex2f (-100.0f, -100.0f); gl->EnableClientState (GL_VERTEX_ARRAY);
glVertex2f (100.0f, -100.0f); gl->EnableClientState (GL_COLOR_ARRAY);
glColor4f (0.0f, 0.0f, 0.2f, 1.0f); gl->VertexPointer (3, GL_FLOAT, 7 * sizeof (gfloat), mesh);
glVertex2f (100.0f, 80.0f); 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, 80.0f);
glVertex2f (-100.0f, 100.0f); gl->DisableClientState (GL_VERTEX_ARRAY);
glVertex2f (100.0f, 100.0f); gl->DisableClientState (GL_COLOR_ARRAY);
glEnd ();
glPopMatrix ();
glMatrixMode (GL_MODELVIEW);
} }
static void static void
gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter, gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter,
gint width, gint height, guint texture, gint width, gint height, guint texture,
gfloat center_x, gfloat center_y, 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); GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter);
GstGLFuncs *gl = filter->display->gl_vtable;
gfloat topy; gfloat w = (gfloat) width;
gfloat bottomy; gfloat h = (gfloat) height;
if (reversed) { gfloat topy = reversed ? center_y - 1.0f : center_y + 1.0f;
topy = center_y - 1.0f; gfloat bottomy = reversed ? center_y + 1.0f : center_y - 1.0f;
bottomy = center_y + 1.0f;
} else {
topy = center_y + 1.0f;
bottomy = 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); GLushort indices[] = {
glEnable (GL_TEXTURE_RECTANGLE_ARB); 0, 1, 2,
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); 0, 2, 3
glDisable (GL_TEXTURE_RECTANGLE_ARB); };
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_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, "width", (gfloat) width);
gst_gl_shader_set_uniform_1f (glass_filter->shader, "height", gst_gl_shader_set_uniform_1f (glass_filter->shader, "height",
(gfloat) height); (gfloat) height);
gst_gl_shader_set_uniform_1f (glass_filter->shader, "yrot", rotation);
glBegin (GL_QUADS); gl->ClientActiveTexture (GL_TEXTURE0);
glColor4f (1.0f, 1.0f, 1.0f, start_alpha); gl->EnableClientState (GL_TEXTURE_COORD_ARRAY);
glTexCoord2i (0, height); gl->EnableClientState (GL_VERTEX_ARRAY);
glVertex2f (center_x - 1.6f, topy); gl->EnableClientState (GL_COLOR_ARRAY);
glTexCoord2i (width, height);
glVertex2f (center_x + 1.6f, topy);
glColor4f (1.0, 1.0, 1.0, stop_alpha); gl->VertexPointer (3, GL_FLOAT, 9 * sizeof (gfloat), mesh);
glTexCoord2i (width, 0); gl->TexCoordPointer (2, GL_FLOAT, 9 * sizeof (gfloat), &mesh[3]);
glVertex2f (center_x + 1.6f, bottomy); gl->ColorPointer (4, GL_FLOAT, 9 * sizeof (gfloat), &mesh[5]);
glTexCoord2i (0, 0);
glVertex2f (center_x - 1.6f, bottomy);
glEnd ();
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) //opengl scene, params: input texture (not the output filter->texture)
static void static void
gst_gl_filter_glass_callback (gint width, gint height, guint texture, gst_gl_filter_glass_callback (gpointer stuff)
gpointer stuff)
{ {
static gint64 start_time = 0; static gint64 start_time = 0;
gfloat rotation;
GstGLFilter *filter = GST_GL_FILTER (stuff); GstGLFilter *filter = GST_GL_FILTER (stuff);
GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (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) if (start_time == 0)
start_time = get_time (); 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_shader_use (glass_filter->passthrough_shader);
gst_gl_filter_glass_draw_background_gradient ();
gst_gl_filter_glass_draw_background_gradient (glass_filter);
//Rotation //Rotation
if (start_time != 0) { if (start_time != 0) {
gint64 time_passed = get_time () - start_time; 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); gl->Enable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl->BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gst_gl_shader_use (glass_filter->shader);
//Reflection //Reflection
gst_gl_filter_glass_draw_video_plane (filter, width, height, texture, 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 //Main video
gst_gl_filter_glass_draw_video_plane (filter, width, height, texture, 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); gst_gl_display_clear_shader (filter->display);
glDisable (GL_BLEND);
gl->Disable (GL_TEXTURE_RECTANGLE_ARB);
gl->Disable (GL_BLEND);
} }

View file

@ -38,8 +38,10 @@ typedef struct _GstGLFilterGlassClass GstGLFilterGlassClass;
struct _GstGLFilterGlass struct _GstGLFilterGlass
{ {
GstGLFilter filter; GstGLFilter filter;
GstGLShader *passthrough_shader;
GstGLShader *shader; GstGLShader *shader;
gint64 timestamp; gint64 timestamp;
guint in_tex;
}; };
struct _GstGLFilterGlassClass struct _GstGLFilterGlassClass