X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fplayback3d.C;h=295ce6fe0a028816217b90f020572eb9a1f715b7;hp=53f6c9e6aa4abc298d6e4c37d9f9125c15fbb4c8;hb=3b4b6f588c4f2643316afcbc486ca6a35c16a431;hpb=8fd64d1d3770c95e2a7cba1049e909cadb4e1fbf diff --git a/cinelerra-5.1/cinelerra/playback3d.C b/cinelerra-5.1/cinelerra/playback3d.C index 53f6c9e6..295ce6fe 100644 --- a/cinelerra-5.1/cinelerra/playback3d.C +++ b/cinelerra-5.1/cinelerra/playback3d.C @@ -271,29 +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 = " 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; 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" - " for( int i=0; i= 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 = @@ -500,12 +521,14 @@ void Playback3D::copy_from_sync(Playback3DCommand *command) // command->frame->get_w(), // command->frame->get_h(), // command->frame->get_color_model()); -// With NVidia at least, +#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) { @@ -705,7 +728,11 @@ void Playback3D::draw_output(Playback3DCommand *command, int flip_y) if(!command->is_cleared) { // If we get here, the virtual console was not used. - color_frame(command, 0,0,0,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 @@ -779,11 +806,14 @@ void Playback3D::clear_output_sync(Playback3DCommand *command) // 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); } + else + color = command->canvas->get_clear_color(); int a = alpha; int r = (color>>16) & 0xff; int g = (color>>8) & 0xff; @@ -1172,6 +1202,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; }; @@ -1204,6 +1235,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); @@ -1211,8 +1243,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 ) { @@ -1220,12 +1253,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]; @@ -1245,7 +1294,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 @@ -1278,11 +1327,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]; @@ -1292,104 +1342,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 > MAX_FEATHER+1 ) n = MAX_FEATHER+1; + 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) ? @@ -1399,19 +1473,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();