/*
* CINELERRA
* Copyright (C) 2009 Adam Williams <broadcast at earthling dot net>
+ * Copyright (C) 2003-2016 Cinelerra CV contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "pluginclient.h"
#include "pluginvclient.h"
#include "edlsession.h"
+#include "track.h"
#include "transportque.inc"
#include "vframe.h"
"#version 430\n"
"layout(location=0) out vec4 color;\n"
"uniform sampler2D tex;\n"
-// apparently, only doubles index properly in shared buffers
- "buffer buf { dvec2 points[]; };\n"
+ "const int MAX = " SS(MAX_FEATHER) "+1;\n"
+ "uniform float psf[MAX];\n"
+ "uniform int n;\n"
+ "uniform vec2 dxy;\n"
+ "uniform vec2 twh;\n"
+ "\n"
+ "void main() {\n"
+ " vec2 tc = gl_FragCoord.xy/textureSize(tex,0);\n"
+ " color = texture(tex, tc);\n"
+ " float c = color.r, f = c*psf[0];\n"
+ " for( int i=1; i<n; ++i ) {\n"
+ " vec2 dd = float(i)*dxy;\n"
+ " vec2 a = tc+dd, ac = min(max(vec2(0.),a), twh);\n"
+ " vec2 b = tc-dd, bc = min(max(vec2(0.),b), twh);\n"
+ " float fa = texture2D(tex, ac).r * psf[i];\n"
+ " float fb = texture2D(tex, bc).r * psf[i];\n"
+ " float m = max(fa, fb);\n"
+ " if( f < m ) f = m;\n"
+ " }\n"
+ " if( c < f ) color = vec4(f);\n"
+ "}\n";
+
+static const char *max_frag =
+ "#version 430\n"
+ "layout(location=0) out vec4 color;\n"
+ "uniform sampler2D tex;\n"
+ "uniform sampler2D tex1;\n"
"uniform float r;\n"
"uniform float v;\n"
+ "\n"
"void main() {\n"
- " vec2 tex_st = gl_FragCoord.xy/textureSize(tex,0);\n"
- " color = texture(tex, tex_st);\n"
- " if( r==0. ) return;\n"
- " float rv = r*v>0. ? 1 : -1;\n"
- " float rr = r*r, dr = 1./rr;\n"
- " float vv = v>=0 ? 1.-v : 1.+v;\n"
- " float fg = rv>=0 ? vv : 1.;\n"
- " float bg = rv>=0 ? 1. : vv;\n"
- " int len = points.length();\n"
- " for( int i=0; i<len; ++i ) {\n"
- " float dx = float(points[i].x) - gl_FragCoord.x;\n"
- " float dy = float(points[i].y) - gl_FragCoord.y;\n"
- " float dd = dx*dx + dy*dy;\n"
- " if( dd >= rr ) continue;\n"
- " float d = dd*dr;\n"
- " float a = (1.-d)*fg + d*bg;\n"
- " if( rv*(color.a-a) > 0 ) color = vec4(a);\n"
- " }\n"
+ " vec2 tc = gl_FragCoord.xy/textureSize(tex,0);\n"
+ " color = texture2D(tex1, tc);\n"
+ " float c = texture2D(tex, tc).r;\n"
+ " float b = r<0 ? 1. : 0.;\n"
+ " if( c == b ) return;\n"
+ " float iv = v>=0. ? 1. : -1.;\n"
+ " float rr = r!=0. ? r : 1.;\n"
+ " float rv = rr*v>=0. ? 1. : -1.;\n"
+ " float vv = v>=0. ? 1.-v : 1.+v;\n"
+ " float fg = rv>0. ? vv : 1.;\n"
+ " float bg = rv>0. ? 1. : vv;\n"
+ " float a = c*fg + (1.-c)*bg;\n"
+ " if( iv*(color.a-a) > 0. ) color = vec4(a);\n"
"}\n";
static const char *multiply_mask4_frag =
if( window ) {
window->enable_opengl();
glFinish();
+ int copy_to_ram = 0;
int w = command->input->get_w();
int h = command->input->get_h();
-
- if(command->input->get_opengl_state() == VFrame::SCREEN &&
- w == command->frame->get_w() && h == command->frame->get_h())
- {
+ if( command->input->get_opengl_state() == VFrame::SCREEN &&
+ w == command->frame->get_w() && h == command->frame->get_h() ) {
// printf("Playback3D::copy_from_sync 1 %d %d %d %d %d\n",
-// command->input->get_w(),
-// command->input->get_h(),
-// command->frame->get_w(),
-// command->frame->get_h(),
+// command->input->get_w(), command->input->get_h(),
+// command->frame->get_w(), command->frame->get_h(),
// command->frame->get_color_model());
-// With NVidia at least,
- if(w % 4)
- {
+#ifdef GLx4
+// With NVidia at least
+ if(w % 4) {
printf("Playback3D::copy_from_sync: w=%d not supported because it is not divisible by 4.\n", w);
}
else
+#endif
// Copy to texture
- if(command->want_texture)
- {
+ if( command->want_texture ) {
//printf("Playback3D::copy_from_sync 1 dst=%p src=%p\n", command->frame, command->input);
// Screen_to_texture requires the source pbuffer enabled.
command->input->enable_opengl();
command->frame->screen_to_texture();
command->frame->set_opengl_state(VFrame::TEXTURE);
}
- else
-// Copy to RAM
- {
+ else {
command->input->to_texture();
- command->input->bind_texture(0);
- command->frame->enable_opengl();
- command->frame->init_screen();
- unsigned int shader = BC_CModels::is_yuv(command->input->get_color_model()) ?
- VFrame::make_shader(0, yuv_to_rgb_frag, 0) : 0;
- if( shader > 0 ) {
- glUseProgram(shader);
- int variable = glGetUniformLocation(shader, "tex");
- glUniform1i(variable, 0);
- BC_GL_YUV_TO_RGB(shader);
- }
- else
- glUseProgram(0);
- command->input->draw_texture(1);
- command->frame->screen_to_ram();
- glUseProgram(0);
+ copy_to_ram = 1;
}
}
- else
- {
+ else if( command->input->get_opengl_state() == VFrame::TEXTURE &&
+ w == command->frame->get_w() && h == command->frame->get_h() ) {
+ copy_to_ram = 1;
+ }
+ else {
printf("Playback3D::copy_from_sync: invalid formats opengl_state=%d %dx%d -> %dx%d\n",
command->input->get_opengl_state(), w, h,
command->frame->get_w(), command->frame->get_h());
}
+
+ if( copy_to_ram ) {
+ command->input->bind_texture(0);
+ command->frame->enable_opengl();
+ command->frame->init_screen();
+ unsigned int shader = BC_CModels::is_yuv(command->input->get_color_model()) ?
+ VFrame::make_shader(0, yuv_to_rgb_frag, 0) : 0;
+ if( shader > 0 ) {
+ glUseProgram(shader);
+ int variable = glGetUniformLocation(shader, "tex");
+ glUniform1i(variable, 0);
+ BC_GL_YUV_TO_RGB(shader);
+ }
+ else
+ glUseProgram(0);
+ command->input->draw_texture(1);
+ command->frame->screen_to_ram();
+ glUseProgram(0);
+ }
}
command->canvas->unlock_canvas();
#endif
if(!command->is_cleared)
{
// If we get here, the virtual console was not used.
- init_frame(command, 0);
+ int color = command->canvas->get_clear_color();
+ int r = (color>>16) & 0xff; // always rgb
+ int g = (color>>8) & 0xff;
+ int b = (color>>0) & 0xff;
+ color_frame(command, r/255.f, g/255.f, b/255.f, 0.f);
}
// Texture
}
-void Playback3D::init_frame(Playback3DCommand *command, int is_yuv)
+void Playback3D::color_frame(Playback3DCommand *command,
+ float r, float g, float b, float a)
{
#ifdef HAVE_GL
- float gbuv = is_yuv ? 0.5 : 0.0;
- glClearColor(0.0, gbuv, gbuv, 0.0);
+ glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
#endif
}
// If we get here, the virtual console is being used.
command->canvas->get_canvas()->enable_opengl();
int is_yuv = 0;
+ int color = BLACK, alpha = 0;
// Using pbuffer for refresh frame.
if( command->frame ) {
command->frame->enable_opengl();
+ command->frame->set_opengl_state(VFrame::SCREEN);
+ color = command->frame->get_clear_color();
+ alpha = command->frame->get_clear_alpha();
int color_model = command->canvas->mwindow->edl->session->color_model;
is_yuv = BC_CModels::is_yuv(color_model);
}
-
- init_frame(command, is_yuv);
+ else
+ color = command->canvas->get_clear_color();
+ int a = alpha;
+ int r = (color>>16) & 0xff;
+ int g = (color>>8) & 0xff;
+ int b = (color>>0) & 0xff;
+ if( is_yuv ) YUV::yuv.rgb_to_yuv_8(r, g, b);
+ color_frame(command, r/255.f, g/255.f, b/255.f, a/255.f);
}
command->canvas->unlock_canvas();
#endif
void bind(int texture_unit);
void read_screen(int x, int y, int w, int h);
void set_output_texture();
+ void unset_output_texture();
GLuint fb, rb;
};
void fb_texture::read_screen(int x, int y, int w, int h)
{
+ bind(1);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glReadBuffer(GL_BACK);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, x,y, w,h);
void fb_texture::set_output_texture()
{
- glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, get_texture_id(), 0);
- GLenum dbo[1] = { GL_COLOR_ATTACHMENT0, }; // bind layout(location=0) out vec4 color;
+ GLenum at = GL_COLOR_ATTACHMENT0;
+ glFramebufferTexture(GL_FRAMEBUFFER, at, get_texture_id(), 0);
+ GLenum dbo[1] = { at, }; // bind layout(location=0) out vec4 color;
glDrawBuffers(1, dbo);
int ret = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if( ret != GL_FRAMEBUFFER_COMPLETE ) {
return;
}
}
+void fb_texture::unset_output_texture()
+{
+ glDrawBuffers(0, 0);
+ int at = GL_COLOR_ATTACHMENT0;
+ glFramebufferTexture(GL_FRAMEBUFFER, at, 0, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glDisable(GL_TEXTURE_2D);
+}
+
+
+class zglTessData : public ArrayList<double *>
+{
+public:
+ zglTessData() { set_array_delete(); }
+ ~zglTessData() { remove_all_objects(); }
+};
static void combineData(GLdouble coords[3],
GLdouble *vertex_data[4], GLfloat weight[4],
GLdouble **outData, void *data)
{
- ArrayList<double *> *invented = (ArrayList<double *> *)data;
+ zglTessData *invented = (zglTessData *)data;
GLdouble *vertex = new double[6];
invented->append(vertex);
vertex[0] = coords[0];
vertex[1] = coords[1];
vertex[2] = coords[2];
for( int i=3; i<6; ++i ) {
- vertex[i] = weight[0] * vertex_data[0][i] +
- weight[1] * vertex_data[1][i] +
- weight[2] * vertex_data[2][i] +
- weight[3] * vertex_data[3][i];
+ GLdouble v = 0;
+ for( int k=0; k<4; ++k ) {
+ if( !weight[k] || !vertex_data[k] ) continue;
+ v += weight[k] * vertex_data[k][i];
+ }
+ vertex[i] = v;
}
*outData = vertex;
}
// dbug
static void zglBegin(GLenum mode) { glBegin(mode); }
static void zglEnd() { glEnd(); }
-static void zglVertex3dv(const GLdouble *v) { glVertex3dv(v); }
+static void zglVertex(const GLdouble *v) { glVertex3dv(v); }
#endif
int w = command->frame->get_w();
int h = command->frame->get_h();
MaskEdges edges;
- float faders[SUBMASKS], feathers[SUBMASKS], bg = 1;
- MaskPointSet point_set[SUBMASKS];
+ float faders[SUBMASKS], feathers[SUBMASKS], cc = 1;
+ MaskPoints point_set[SUBMASKS];
// Draw every submask as a new polygon
int total_submasks = command->keyframe_set->total_submasks(
command->start_position_project, PLAY_FORWARD);
+ int show_mask = command->keyframe_set->track->masks;
for(int k = 0; k < total_submasks; k++) {
- MaskPointSet &points = point_set[k];
+ MaskPoints &points = point_set[k];
command->keyframe_set->get_points(&points,
k, command->start_position_project, PLAY_FORWARD);
float fader = command->keyframe_set->get_fader(
command->start_position_project, k, PLAY_FORWARD);
float v = fader/100.;
faders[k] = v;
- if( v < 0 && (v+=1) < bg ) bg = v;
float feather = command->keyframe_set->get_feather(
command->start_position_project, k, PLAY_FORWARD);
feathers[k] = feather;
- }
-// clear screen
- glDisable(GL_TEXTURE_2D);
- glClearColor(bg, bg, bg, bg);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- for(int k = 0; k < total_submasks; k++) {
- MaskPointSet &points = point_set[k];
MaskEdge &edge = *edges.append(new MaskEdge());
- int first_point = 0;
-// Need to tabulate every vertex in persistent memory because
-// gluTessVertex doesn't copy them.
- for(int i = 0; i < points.total; i++) {
- MaskPoint *point1 = points.values[i];
- MaskPoint *point2 = (i >= points.total - 1) ?
- points.values[0] : points.values[i + 1];
-
- float x, y;
- int segments = 0;
- if( point1->control_x2 == 0 && point1->control_y2 == 0 &&
- point2->control_x1 == 0 && point2->control_y1 == 0 )
- segments = 1;
-
- float x0 = point1->x, y0 = point1->y;
- float x1 = point1->x + point1->control_x2;
- float y1 = point1->y + point1->control_y2;
- float x2 = point2->x + point2->control_x1;
- float y2 = point2->y + point2->control_y1;
- float x3 = point2->x, y3 = point2->y;
-
- // forward differencing bezier curves implementation taken from GPL code at
- // http://cvs.sourceforge.net/viewcvs.py/guliverkli/guliverkli/src/subtitles/Rasterizer.cpp?rev=1.3
-
- float cx3, cx2, cx1, cx0, cy3, cy2, cy1, cy0;
-
- // [-1 +3 -3 +1]
- // [+3 -6 +3 0]
- // [-3 +3 0 0]
- // [+1 0 0 0]
-
- cx3 = - x0 + 3*x1 - 3*x2 + x3;
- cx2 = 3*x0 - 6*x1 + 3*x2;
- cx1 = -3*x0 + 3*x1;
- cx0 = x0;
-
- cy3 = - y0 + 3*y1 - 3*y2 + y3;
- cy2 = 3*y0 - 6*y1 + 3*y2;
- cy1 = -3*y0 + 3*y1;
- cy0 = y0;
-
- // This equation is from Graphics Gems I.
- //
- // The idea is that since we're approximating a cubic curve with lines,
- // any error we incur is due to the curvature of the line, which we can
- // estimate by calculating the maximum acceleration of the curve. For
- // a cubic, the acceleration (second derivative) is a line, meaning that
- // the absolute maximum acceleration must occur at either the beginning
- // (|c2|) or the end (|c2+c3|). Our bounds here are a little more
- // conservative than that, but that's okay.
- if (segments == 0) {
- float maxaccel1 = fabs(2*cy2) + fabs(6*cy3);
- float maxaccel2 = fabs(2*cx2) + fabs(6*cx3);
-
- float maxaccel = maxaccel1 > maxaccel2 ? maxaccel1 : maxaccel2;
- float h = 1.0;
-
- if(maxaccel > 8.0) h = sqrt((8.0) / maxaccel);
- segments = int(1/h);
- }
+ if( !v || !((show_mask>>k) & 1) || !points.size() ) continue;
+ edge.load(point_set[k], h);
+ if( v >= 0 ) continue;
+ float vv = 1 + v;
+ if( cc > vv ) cc = vv;
+ }
- for(int j = 0; j <= segments; j++) {
- float t = (float)j / segments;
- x = cx0 + t*(cx1 + t*(cx2 + t*cx3));
- y = cy0 + t*(cy1 + t*(cy2 + t*cy3));
+ fb_texture *mask = new fb_texture(w, h, color_model);
+ mask->set_output_texture();
+ glClearColor(cc, cc, cc, cc);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ mask->unset_output_texture();
- if(j > 0 || first_point) {
- edge.append(x, y - h);
- first_point = 0;
- }
- }
- }
- if( edge.size() > 0 ) {
-// draw polygon
- float fader = faders[k];
- float v = fader < 0 ? 1 : 1-fader;
- glColor4f(v, v, v, v);
+ unsigned int feather_shader =
+ VFrame::make_shader(0, in_vertex_frag, feather_frag, 0);
+ unsigned int max_shader =
+ VFrame::make_shader(0, in_vertex_frag, max_frag, 0);
+ if( feather_shader && max_shader ) {
+ fb_texture *in = new fb_texture(w, h, color_model);
+ fb_texture *out = new fb_texture(w, h, color_model);
+ float tw = 1./out->get_texture_w(), th = 1./out->get_texture_h();
+ float tw1 = (w-1)*tw, th1 = (h-1)*th;
+ for(int k = 0; k < total_submasks; k++) {
+ MaskEdge &edge = *edges[k];
+ if( edge.size() < 3 ) continue;
+ float r = feathers[k], v = faders[k];
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glActiveTexture(GL_TEXTURE0);
+ glDisable(GL_TEXTURE_2D);
+ float b = r>=0 ? 0. : 1.;
+ float f = r>=0 ? 1. : 0.;
+ glClearColor(b, b, b, b);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glColor4f(f, f, f, f);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
int display_list = glGenLists(1);
- glNewList(display_list, GL_COMPILE);
#if 0
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glNewList(display_list, GL_COMPILE);
glBegin(GL_POLYGON);
MaskCoord *c = &edge[0];
for( int i=edge.size(); --i>=0; ++c )
glVertex2f(c->x, c->y);
glEnd();
+ glEndList();
+ glCallList(display_list);
#else
+ { zglTessData invented;
GLUtesselator *tess = gluNewTess();
- gluTessCallback(tess, GLU_TESS_VERTEX,(GLvoid (*)()) &zglVertex3dv);
+ gluTessProperty(tess, GLU_TESS_TOLERANCE, 0.5);
+ gluTessCallback(tess, GLU_TESS_VERTEX,(GLvoid (*)()) &zglVertex);
gluTessCallback(tess, GLU_TESS_BEGIN,(GLvoid (*)()) &zglBegin);
gluTessCallback(tess, GLU_TESS_END,(GLvoid (*)()) &zglEnd);
gluTessCallback(tess, GLU_TESS_COMBINE_DATA,(GLvoid (*)()) &combineData);
- ArrayList<double *> invented;
- invented.set_array_delete();
-
- gluTessBeginPolygon(tess, &invented);
+ glNewList(display_list, GL_COMPILE);
+ gluTessBeginPolygon(tess, &invented);
gluTessBeginContour(tess);
MaskCoord *c = &edge[0];
for( int i=edge.size(); --i>=0; ++c )
gluTessVertex(tess, (GLdouble *)c, c);
gluTessEndContour(tess);
- gluTessEndPolygon(tess);
- gluDeleteTess(tess);
- invented.remove_all_objects();
-#endif
+ gluTessEndPolygon(tess);
glEndList();
glCallList(display_list);
+ gluDeleteTess(tess); }
+#endif
glDeleteLists(1, display_list);
- }
- }
-
-// in/out textures
- fb_texture *in = new fb_texture(w, h, color_model);
- in->bind(0);
- in->read_screen(0,0, w,h);
- fb_texture *out = new fb_texture(w, h, color_model);
-
- unsigned int frag_shader =
- VFrame::make_shader(0, in_vertex_frag, feather_frag, 0);
- if( frag_shader > 0 ) {
- GLuint points[1];
- glGenBuffers(1, points);
- for(int k = 0; k < total_submasks; k++) {
- MaskEdge &edge = *edges[k];
- if( !edge.size() ) continue;
- if( !faders[k] ) continue;
- if( !feathers[k] ) continue;
- MaskSpots spots;
- for( int i=0; i<edge.size(); ++i ) {
- MaskCoord &a = edge[i];
- MaskCoord &b = i<edge.size()-1 ? edge[i+1] : edge[0];
- draw_spots(spots, a.x,a.y+h, b.x,b.y+h);
+ in->read_screen(0,0, w,h);
+//in->write_tex("/tmp/in0.ppm");
+ if( r ) {
+ double sig2 = -log(255.0)/(r*r);
+ int n = abs((int)r) + 1;
+ if( n > MAX_FEATHER+1 ) n = MAX_FEATHER+1;
+ float psf[n]; // point spot fn
+ for( int i=0; i<n; ++i )
+ psf[i] = exp(i*i * sig2);
+ glUseProgram(feather_shader);
+ glUniform1fv(glGetUniformLocation(feather_shader, "psf"), n, psf);
+ glUniform1i(glGetUniformLocation(feather_shader, "n"), n);
+ glUniform2f(glGetUniformLocation(feather_shader, "dxy"), tw, 0.);
+ glUniform2f(glGetUniformLocation(feather_shader, "twh"), tw1, th1);
+ glUniform1i(glGetUniformLocation(feather_shader, "tex"), 0);
+ in->bind(0);
+ out->set_output_texture();
+ out->draw_texture(0,0, w,h, 0,0, w,h);
+ out->unset_output_texture();
+//out->write_tex("/tmp/out1.ppm");
+ fb_texture *t = in; in = out; out = t;
+ glUniform2f(glGetUniformLocation(feather_shader, "dxy"), 0., th);
+ in->bind(0);
+ out->set_output_texture();
+ out->draw_texture(0,0, w,h, 0,0, w,h);
+ out->unset_output_texture();
+//out->write_tex("/tmp/out2.ppm");
+ glUseProgram(0);
+ t = in; in = out; out = t;
}
- int sz = spots.size() * sizeof(MaskSpot);
- glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, points[0], 0, sz);
- glBufferData(GL_SHADER_STORAGE_BUFFER, sz, &spots[0], GL_DYNAMIC_COPY);
- glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
- glUseProgram(frag_shader);
- float r = feathers[k], v = faders[k];
- glUniform1f(glGetUniformLocation(frag_shader, "r"), r);
- glUniform1f(glGetUniformLocation(frag_shader, "v"), v);
+
+ glUseProgram(max_shader);
in->bind(0);
- glUniform1i(glGetUniformLocation(frag_shader, "tex"), 0);
- out->set_output_texture();
+//in->write_tex("/tmp/in1.ppm");
+//mask->write_tex("/tmp/mask1.ppm");
+ mask->bind(1);
+ glUniform1i(glGetUniformLocation(max_shader, "tex"), 0);
+ glUniform1i(glGetUniformLocation(max_shader, "tex1"), 1);
+ glUniform1f(glGetUniformLocation(max_shader, "r"), r);
+ glUniform1f(glGetUniformLocation(max_shader, "v"), v);
glViewport(0,0, w,h);
+ out->set_output_texture();
out->draw_texture(0,0, w,h, 0,0, w,h);
+ out->unset_output_texture();
glUseProgram(0);
- fb_texture *t = in; in = out; out = t;
+ fb_texture *t = mask; mask = out; out = t;
+//mask->write_tex("/tmp/mask2.ppm");
}
- glDeleteBuffers(1, points);
+ delete in;
+ delete out;
}
- glDrawBuffers(0, 0);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
const char *alpha_shader = BC_CModels::has_alpha(color_model) ?
multiply_mask4_frag :
!BC_CModels::is_yuv(color_model) ?
glUseProgram(shader);
if( shader > 0 ) {
command->frame->bind_texture(0);
- in->BC_Texture::bind(1);
+ mask->BC_Texture::bind(1);
glUniform1i(glGetUniformLocation(shader, "tex"), 0);
glUniform1i(glGetUniformLocation(shader, "tex1"), 1);
}
command->frame->draw_texture();
command->frame->set_opengl_state(VFrame::SCREEN);
glUseProgram(0);
- delete in;
- delete out;
-// Default drawable
- glDisable(GL_TEXTURE_2D);
+ delete mask;
glColor4f(1, 1, 1, 1);
glActiveTexture(GL_TEXTURE0);
+ glDisable(GL_TEXTURE_2D);
window->enable_opengl();
}
command->canvas->unlock_canvas();