# HG changeset patch # User Markus Mützel # Date 1469288732 -7200 # Node ID 20b225a3ebf8ab650d6de437f41534464aead31b # Parent 8971508e21c8c5c0d4f138edc06b09e4d0c241e6 Update to light (patch #8943) * gl-render.h, gl-render.cc (get_maxlights): New static function. (opengl_renderer::max_lights): New data member. (opengl_renderer::opengl_renderer): Use get_maxlights to initialize max_lights data member. (opengl_renderer::draw_all_lights): New function. Support local light sources. (opengl_renderer::draw_axes_children): Call draw_all_lights instead of doing the work here. (opengl_renderer::draw_surface): Remove warning for "phong". * scripts/plot/draw/light.m: Update docstring. Add and update demos. * doc/interpreter/genpropdoc.m: Update docstring. diff -r 8971508e21c8 -r 20b225a3ebf8 doc/interpreter/genpropdoc.m --- a/doc/interpreter/genpropdoc.m Thu Jul 28 16:38:37 2016 -0400 +++ b/doc/interpreter/genpropdoc.m Sat Jul 23 17:45:32 2016 +0200 @@ -1305,8 +1305,7 @@ case "style" s.doc = "This string defines whether the light emanates from a \ light source at infinite distance (@qcode{\"infinite\"}) or from a local \ -point source (@qcode{\"local\"}). Only the default value @qcode{\"infinite\"} \ -is supported."; +point source (@qcode{\"local\"})."; endswitch diff -r 8971508e21c8 -r 20b225a3ebf8 libinterp/corefcn/gl-render.cc --- a/libinterp/corefcn/gl-render.cc Thu Jul 28 16:38:37 2016 -0400 +++ b/libinterp/corefcn/gl-render.cc Sat Jul 23 17:45:32 2016 +0200 @@ -587,6 +587,33 @@ #endif +static int +get_maxlights (void) +{ +#if defined (HAVE_OPENGL) + + static int max_lights = 0; + + // Check actual maximum number of lights possible + if (max_lights == 0) + { + for (max_lights = 0; max_lights < GL_MAX_LIGHTS; max_lights++) + { + glDisable (GL_LIGHT0 + max_lights); + if (glGetError ()) + break; + } + } + + return max_lights; +#else + + err_disabled_feature ("opengl_renderer", "OpenGL"); + +#endif + +} + opengl_renderer::opengl_renderer (void) : toolkit (), xform (), xmin (), xmax (), ymin (), ymax (), zmin (), zmax (), xZ1 (), xZ2 (), marker_id (), filled_marker_id (), @@ -606,6 +633,9 @@ if (! ok) error ("the size of GLsizei is smaller than the size of int"); + // Check actual maximum number of lights possible + max_lights = get_maxlights (); + #else err_disabled_feature ("opengl_renderer", "OpenGL"); @@ -1618,13 +1648,43 @@ } void +opengl_renderer::draw_all_lights (const base_properties& props, std::list& obj_list) +{ + Matrix children = props.get_all_children (); + + for (octave_idx_type i = children.numel () - 1; i >= 0; i--) + { + graphics_object go = gh_manager::get_object (children(i)); + + if (go.get_properties ().is_visible ()) + { + if (go.isa ("light")) + { + if (num_lights < max_lights) + { + current_light = GL_LIGHT0 + num_lights; + set_clipping (go.get_properties ().is_clipping ()); + draw (go); + num_lights++; + } + else + warning_with_id ("Octave:max-lights-exceeded", + "light: Maximum number of lights (%d) in these axes is " + "exceeded.", max_lights); + } + else if (go.isa ("hggroup")) + draw_all_lights (go.get_properties (), obj_list); + else + obj_list.push_back (go); + } + } +} + +void opengl_renderer::draw_axes_children (const axes::properties& props) { #if defined (HAVE_OPENGL) - - // Children - - Matrix children = props.get_all_children (); + // list for non-light child objects std::list obj_list; std::list::iterator it; @@ -1634,30 +1694,10 @@ // display them in the order they were added to the array. num_lights = 0; - - for (octave_idx_type i = children.numel () - 1; i >= 0; i--) - { - graphics_object go = gh_manager::get_object (children(i)); - - if (go.get_properties ().is_visible ()) - { - if (go.isa ("light")) - { - if (num_lights < GL_MAX_LIGHTS) - { - current_light = GL_LIGHT0 + num_lights; - set_clipping (go.get_properties ().is_clipping ()); - draw (go); - num_lights++; - } - } - else - obj_list.push_back (go); - } - } + draw_all_lights (props, obj_list); // disable other OpenGL lights - for (int i = num_lights; i < GL_MAX_LIGHTS; i++) + for (int i = num_lights; i < max_lights; i++) glDisable (GL_LIGHT0 + i); // save camera position and set ambient light color before drawing @@ -1943,9 +1983,6 @@ // FIXME: handle transparency Matrix a; - if (props.facelighting_is ("phong") || props.edgelighting_is ("phong")) - warning ("opengl_renderer: phong light model not supported"); - int fc_mode = (props.facecolor_is_rgb () ? 0 : (props.facecolor_is ("flat") ? 1 : (props.facecolor_is ("interp") ? 2 : @@ -2296,7 +2333,7 @@ cb[k] = c(j-1, i, k); glColor3fv (cb); - if (fl_mode > 0) + if (el_mode > 0) { for (int k = 0; k < 3; k++) cb[k] *= as; @@ -2323,7 +2360,7 @@ cb[k] = c(j, i, k); glColor3fv (cb); - if (fl_mode > 0) + if (el_mode > 0) { for (int k = 0; k < 3; k++) cb[k] *= as; @@ -2393,7 +2430,7 @@ cb[k] = c(j, i-1, k); glColor3fv (cb); - if (fl_mode > 0) + if (el_mode > 0) { for (int k = 0; k < 3; k++) cb[k] *= as; @@ -2420,7 +2457,7 @@ cb[k] = c(j, i, k); glColor3fv (cb); - if (fl_mode > 0) + if (el_mode > 0) { for (int k = 0; k < 3; k++) cb[k] *= as; @@ -3015,10 +3052,12 @@ glEnable (current_light); // light position - float pos[4] = { 0, 0, 0, 0 }; // X,Y,Z,attenuation + float pos[4] = { 0, 0, 0, 0 }; // X,Y,Z,infinite/local Matrix lpos = props.get_position ().matrix_value (); for (int i = 0; i < 3; i++) pos[i] = lpos(i); + if (props.style_is ("local")) + pos[3] = 1; glLightfv (current_light, GL_POSITION, pos); // light color diff -r 8971508e21c8 -r 20b225a3ebf8 libinterp/corefcn/gl-render.h --- a/libinterp/corefcn/gl-render.h Thu Jul 28 16:38:37 2016 -0400 +++ b/libinterp/corefcn/gl-render.h Sat Jul 23 17:45:32 2016 +0200 @@ -169,6 +169,8 @@ void draw_axes_children (const axes::properties& props); + void draw_all_lights (const base_properties& props, std::list& obj_list); + private: // The graphics toolkit associated with the figure being rendered. graphics_toolkit toolkit; @@ -198,6 +200,7 @@ // light object present and visible int num_lights; unsigned int current_light; + int max_lights; private: class patch_tesselator; diff -r 8971508e21c8 -r 20b225a3ebf8 scripts/plot/draw/light.m --- a/scripts/plot/draw/light.m Thu Jul 28 16:38:37 2016 -0400 +++ b/scripts/plot/draw/light.m Sat Jul 23 17:45:32 2016 +0200 @@ -51,8 +51,7 @@ ## ## @item @qcode{"Style":} This string defines whether the light emanates from a ## light source at infinite distance (@qcode{"infinite"}) or from a local point -## source (@qcode{"local"}). Only the default value @qcode{"infinite"} is -## supported. +## source (@qcode{"local"}). ## @end table ## ## If @command{light} is called with an axes handle @var{hax}, it must be passed @@ -177,7 +176,7 @@ %! %% Diffuse and specular reflex %! clf; %! h_axes = axes (); -%! [x,y,z] = meshgrid (-.2:0.02:.2, -.2:0.02:.2, -.2:0.02:.2); +%! [x,y,z] = meshgrid (-.2:0.04:.2, -.2:0.04:.2, -.2:0.04:.2); %! val = (x.^2 + y.^2 + z.^2); %! %! fv = isosurface (x, y, z, val, .039); @@ -297,7 +296,7 @@ %!demo %! %% Specular Exponent %! clf; -%! [x,y,z] = meshgrid (-.2:0.01:.2, -.2:0.01:.2, -.2:0.01:.2); +%! [x,y,z] = meshgrid (-.2:0.02:.2, -.2:0.02:.2, -.2:0.02:.2); %! val = (x.^2 + y.^2 + z.^2); %! %! h_axes = axes (); @@ -380,7 +379,7 @@ %!demo %! %% Colored patch %! clf; -%! [x,y,z] = meshgrid (-.2:0.01:.2, -.2:0.01:.2, -.2:0.01:.2); +%! [x,y,z] = meshgrid (-.2:0.02:.2, -.2:0.02:.2, -.2:0.02:.2); %! val = (x.^2 + y.^2 + z.^2); %! %! h_axes = axes (); @@ -389,11 +388,72 @@ %! "FaceLighting", "Gouraud"); %! set (h_patch, "SpecularExponent", 15); %! isonormals (x, y, z, val, h_patch); +%! title ('Colored patch'); %! h_light = light ("Position", [-1 1 1]); %! axis tight %! axis equal %! view (3); +%!demo +%! %% Colored mesh (patch) +%! clf; +%! [x,y,z] = meshgrid (-.2:0.05:.2, -.2:0.05:.2, -.2:0.05:.2); +%! val = (x.^2 + y.^2 + z.^2); +%! +%! h_axes = axes (); +%! fv = isosurface (x, y, z, val, .039, z); +%! h_patch = patch (fv, 'FaceColor', 'w', 'EdgeColor', 'interp'); +%! isonormals (x, y, z, val, h_patch); +%! title ('Colored mesh (patch)'); +%! h_light = light; +%! lighting gouraud +%! axis tight +%! axis equal +%! view (3); + +%!demo +%! %% Colored mesh (surface) +%! clf; +%! h_mesh = mesh (peaks); +%! title ('Colored mesh (surface)'); +%! h_light = light; +%! lighting gouraud + +%!demo +%! %% Light in hggroup +%! clf; +%! h_mesh = mesh (peaks); +%! h_hg = hggroup (); +%! title ('Light in hggroup'); +%! h_light = light ('Parent', h_hg); +%! lighting gouraud + +%!demo +%! %% Style local/infinite +%! clf; +%! [x,y,z] = meshgrid (-.2:0.02:.2, -.2:0.02:.2, -.2:0.02:.2); +%! val = (x.^2 + y.^2 + z.^2); +%! +%! h_axes1 = subplot (1,2,1); +%! fv = isosurface (x, y, z, val, .039); +%! h_patch = patch (fv, 'FaceColor', 'r', 'EdgeColor', 'none'); +%! isonormals (x, y, z, val, h_patch); +%! title ('"Style" set to "infinite" (default)'); +%! h_light = light ('Position', [.3 0 .3]); +%! lighting gouraud +%! axis equal +%! view (3); +%! +%! h_axes2 = subplot (1,2,2); +%! fv = isosurface (x, y, z, val, .039); +%! h_patch = patch (fv, 'FaceColor', 'r', 'EdgeColor', 'none'); +%! isonormals (x, y, z, val, h_patch); +%! title ('"Style" set to "local"'); +%! h_light = light ('Style', 'local', 'Position', [.3 0 .3]); +%! lighting gouraud +%! axis equal +%! view (3); + %!test %! hf = figure ("Visible", "off");