[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_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);
}

View file

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