X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fplayback3d.C;fp=cinelerra-5.1%2Fcinelerra%2Fplayback3d.C;h=503e57185b1c01d14462e25a02ea50f93c7933f4;hp=f5ef5c4f6b866c88601ba1a8717e19f08627efea;hb=8e67d840c5a93f77de021102a4f0bfc4e07504f4;hpb=b350aa5a1ccbadcb5f794183c443c0738cd1e9ab diff --git a/cinelerra-5.1/cinelerra/playback3d.C b/cinelerra-5.1/cinelerra/playback3d.C index f5ef5c4f..503e5718 100644 --- a/cinelerra-5.1/cinelerra/playback3d.C +++ b/cinelerra-5.1/cinelerra/playback3d.C @@ -271,31 +271,50 @@ static const char *feather_frag = "#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 = 1024;\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; i0. ? 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" - " float sig2 = -log(255.0);\n" - " for( int i=0; i= rr ) continue;\n" - " float ss = dd / rr;\n" - " float d = exp(ss * sig2);\n" - " float a = d*fg + (1.-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 = @@ -1174,6 +1193,7 @@ public: 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; }; @@ -1206,6 +1226,7 @@ void fb_texture::bind(int texture_unit) 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); @@ -1213,8 +1234,9 @@ void fb_texture::read_screen(int x, int y, int w, int 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 ) { @@ -1222,12 +1244,28 @@ void fb_texture::set_output_texture() 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 +{ +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 *invented = (ArrayList *)data; + zglTessData *invented = (zglTessData *)data; GLdouble *vertex = new double[6]; invented->append(vertex); vertex[0] = coords[0]; @@ -1247,7 +1285,7 @@ static void combineData(GLdouble coords[3], // 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 @@ -1280,11 +1318,12 @@ void Playback3D::do_mask_sync(Playback3DCommand *command) int w = command->frame->get_w(); int h = command->frame->get_h(); MaskEdges edges; - float faders[SUBMASKS], feathers[SUBMASKS], bg = 1; + 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++) { MaskPoints &points = point_set[k]; @@ -1294,104 +1333,128 @@ void Playback3D::do_mask_sync(Playback3DCommand *command) 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; + MaskEdge &edge = *edges.append(new MaskEdge()); + 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; } -// clear screen - glDisable(GL_TEXTURE_2D); - glClearColor(bg, bg, bg, bg); + + 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(); - int show_mask = command->keyframe_set->track->masks; - for(int k = 0; k < total_submasks; k++) { - MaskEdge &edge = *edges.append(new MaskEdge()); - if( !((show_mask>>k) & 1) ) continue; - edge.load(point_set[k], h); - 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 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; iread_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 > 1024 ) n = 1024; // MAX + float psf[n]; // point spot fn + for( int i=0; ibind(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) ? @@ -1401,19 +1464,17 @@ void Playback3D::do_mask_sync(Playback3DCommand *command) 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();