Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
problem with surface lighting (OpenGL)

Subject: problem with surface lighting (OpenGL)

From: Andres

Date: 16 Apr, 2009 12:14:01

Message: 1 of 7

Dear all,
please compare the surface lighting of the following four plots:

% -----------------------------------
[Y,Z,X] = cylinder([1.2 1 1 0.8],72); % "[Y,Z,X]"!
X(3:end,:) = X(3:end,:)+0.5;

figure(1)
surf(X,Y,Z,'EdgeAlpha',0.2,'FaceColor','c')
axis equal off
light('Position',[0 0 1],'Style','infinite');

idxShift = mod(1:73,4)>1;
X(3,idxShift) = X(3,idxShift)+0.2;

figure(2)
surf(X,Y,Z,'EdgeAlpha',0.2,'FaceColor','c')
axis equal off
light('Position',[0 0 1],'Style','infinite');

figure(3)
surf(X(1:3,:),Y(1:3,:),Z(1:3,:),'EdgeAlpha',0.2,'FaceColor','c')
axis equal off
light('Position',[0 0 1],'Style','infinite');

figure(4)
surf(X(1:3,:),Y(1:3,:),Z(1:3,:),'EdgeAlpha',0.2,'FaceColor','c')
hold on
surf(X(3:4,:),Y(3:4,:),Z(3:4,:),'EdgeAlpha',0.2,'FaceColor','c')
axis equal off
light('Position',[0 0 1],'Style','infinite');
% -----------------------------------


I am not happy with the surface of figure 2 - which represents the one I need, of course :-(
The inner faces are irreguarly lit and look zebra-like, unlike those in the other figures (in my real application the effect is even worse).
Figure 4 comes close to what I want and expect, except for the double edge lines, but anyhow breaking up the mesh is not an option.
The renderer 'zbuffer' always gives a good face lighting, btw, but I need to control the transparency of the surface and the edges.

So is there any good explanation for why fig. 2 looks so different from fig. 4?
And hopefully even a workaround?
Thanks for your thoughts
Andres

Subject: problem with surface lighting (OpenGL)

From: Oliver Woodford

Date: 17 Apr, 2009 10:03:01

Message: 2 of 7

It looks to me like the face normals are being incorrectly calculated here. I would submit it as a bug report and see what happens.

Subject: problem with surface lighting (OpenGL)

From: Andres

Date: 17 Apr, 2009 12:23:02

Message: 3 of 7

"Oliver Woodford" <o.j.woodford.98@cantab.net> wrote in message <gs9k4l$3c4$1@fred.mathworks.com>...
> It looks to me like the face normals are being incorrectly calculated here. I would submit it as a bug report and see what happens.

Thanks for your answer, Oliver, so I'm not the only one observing the zebra. It's remarkable that the face normal calculation should depend on the existence or shape of neighbouring faces.
In the meantime I've sent in a service request. To strengthen the effect, I've increased the number of faces:


[Y,Z,X] = cylinder([1.2 1 1 0.8],144); % "[Y,Z,X]"!
X(3:end,:) = X(3:end,:)+0.5;

figure(1)
surf(X,Y,Z,'EdgeAlpha',0.2,'FaceColor','c')
axis equal off
light('Position',[0 0 1],'Style','infinite');

idxShift = mod(1:size(X,2),4)>1;
X(3,idxShift) = X(3,idxShift)+0.2;

figure(2)
surf(X,Y,Z,'EdgeAlpha',0.2,'FaceColor','c')
axis equal off
light('Position',[0 0 1],'Style','infinite');

figure(3)
surf(X(1:3,:),Y(1:3,:),Z(1:3,:),'EdgeAlpha',0.2,'FaceColor','c')
axis equal off
light('Position',[0 0 1],'Style','infinite');

figure(4)
surf(X(1:3,:),Y(1:3,:),Z(1:3,:),'EdgeAlpha',0.2,'FaceColor','c')
hold on
surf(X(3:4,:),Y(3:4,:),Z(3:4,:),'EdgeAlpha',0.2,'FaceColor','c')
axis equal off
light('Position',[0 0 1],'Style','infinite');

Subject: problem with surface lighting (OpenGL)

From: Michael Garrity

Date: 17 Apr, 2009 14:04:52

Message: 4 of 7

>"Andres" <rantore@werb.deNoRs> wrote in message news:gs77e9$fbj$1@fred.mathworks.com...
> Dear all,
> please compare the surface lighting of the following four plots:
>

Sorry, there's a bug in the opengl renderer that's causing it to
use the wrong normals. It uses the vertex normals instead of
the face normals in this case. If you switch your renderer to
zbuffer instead of opengl, you'll get the correct lighting in this
case.

    Mike Garrity
    The MathWorks

Subject: problem with surface lighting (OpenGL)

From: Chaos

Date: 19 Apr, 2009 11:17:02

Message: 5 of 7

"Andres" <rantore@werb.deNoRs> wrote in message
>
> So is there any good explanation for why fig. 2 looks so different from fig. 4?
> And hopefully even a workaround?
> Thanks for your thoughts
> Andres
\

i have found so many bugs in the opengl implementation, it's a running joke in these parts. we have the latest screaming ATI cards and have to dumb them down to other renderers.

there is a kluge of a work around we've found, if you setup how things 'should' look even though on screen they look wrong, modify your graphic call to turn off the "Visibility" and write directly to disk in a tif or whatever. we got lucky and the images on disk are correct even when display is wrong. i did a complete manual mode and it works.

no thanks to anyone on this forum.

plot_set=figure('Units','pixels','Position',iPos,...
  'OuterPosition',oPos,'InvertHardCopy', 'off',...
  'ActivePositionProperty','OuterPosition','Visible','off',...
  'Renderer','OpenGl','RendererMode','manual','doubleBuffer','off',...
  'MenuBar','none','NextPlot','replacechildren','ToolBar','none',...
  'Color',[0.2 0.6 0.9],'DefaultAxesXColor',[.85 .85 0],'DefaultAxesYColor',[.85 .85 0],...
  'PaperOrientation', 'portrait','PaperPositionMode','auto',...
  'DefaultAxesXMinorGrid','on','DefaultAxesYMinorGrid','off','DefaultAxesTickDir','in',...
  'DefaultAxesXMinorTick','on','DefaultAxesMinorGridLineStyle',':','DefaultLineLineStyle','-');

Subject: problem with surface lighting (OpenGL)

From: Andres

Date: 20 Apr, 2009 19:20:02

Message: 6 of 7

Thank you, Chaos, for your support, but I had no success with your figure settings and direct printing.
And thanks to Mike for your bug confirmation. Your post gave me the idea to compute the face normals by myself and simply use them with the 'VertexNormals' parameter in surf.
I've written a small function, 'facenorm':

% ---
function N = facenorm(X,Y,Z)

% FACENORM compute alternate surface normals to be used with surface plots
%
% ...

% input checking left to surf et.al. ...

coord = cat(3,X,Y,Z);

% edge vectors of a face
d11 = diff(coord(:,1:end-1,:),1,1);
d12 = diff(coord(1:end-1,:,:),1,2);

% opposite edge vectors
d21 = diff(coord(end:-1:1,end:-1:2,:),1,1);
d22 = diff(coord(end:-1:2,end:-1:1,:),1,2);

% normals of the opposing edges
n1 = cross(d12,d11,3);
n2 = cross(d22,d21,3);

% add the normals to get an average normal of the face
n = n1 + n2(end:-1:1,end:-1:1,:);

% prepare for surf and normalize
N = NaN(size(n)+[1 1 0]);
N(2:end,2:end,:) = n;
mag = sqrt(sum(N.^2,3));
mag(mag==0)=eps;
N = N./repmat(mag,[1 1 3]);

% ---

See what it does:

  % generate some demo data
  [Y,Z,X] = cylinder([0.8 1 1 0.8],144);
  idxShift = mod(1:size(X,2),4)>1;
  X(2,idxShift) = X(2,idxShift)-0.2;
  X(3,idxShift) = X(3,idxShift)+0.2;
 
  % standard surf plot
  figure(1)
  surf(X,Y,Z,'EdgeAlpha',0.2,'FaceColor','c')
  axis equal
  light('Position',[0 0 1],'Style','infinite')
  view(0,60)
  
  % same plot with alternate surface normals
  % (giving a symmetrical lighting as it should)
  figure(10)
  surf(X,Y,Z,'EdgeAlpha',0.2,'FaceColor','c',...
             'VertexNormals',facenorm(X,Y,Z))
  axis equal
  light('Position',[0 0 1],'Style','infinite')
  view(0,60)

To me, the second plot looks quite promising, but I'm not sure whether it will work in general, or what drawbacks there are. If anyone likes to look at it, I'd be glad (e.g. I heavily suspect it can be simplified), but hopefully it does the trick for me as it is.

Subject: problem with surface lighting (OpenGL)

From: Andres

Date: 25 Apr, 2009 19:21:01

Message: 7 of 7

I've put the workaround to
http://www.mathworks.de/matlabcentral/fileexchange/23882

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us