Java 2D开发技巧之“灯光与阴影”
时间:2011-01-05 天极 朱先忠
一、引言
在本文中,我们将向你展示如何为扁平形状添加一种灯光效果以实现一种类3D外观。
也许你比较满意于自己的文字表达能力,但一幅图片往往能够产生更好的效果。对于图形处理来说,也是如此;不妨请参考一下图1中的两种图形。在本文中,我将向你展示如何克服左边扁平形状所带来的烦恼而以一种更为光滑的更具舒服感的形状代替。
图1.普通扁平形状与施加Java 2D效果后的形状
二、实现技术分析
借助于适当的颜色,你可以使用本文中介绍的技术来模拟一种彩色光闪耀"越过"你的形状,从而生成一种微妙的发光效果。我们是如何实现这一效果的呢?请分析下面的代码;在方法drawBorderGlow()上面的注释更为细致地介绍了关键实现方法:
import java.awt.geom.*;
import java.awt.image.*;
private static final Color clrHi = new Color(255, 229, 63);
private static final Color clrLo = new Color(255, 105, 0);
private static final Color clrGlowInnerHi = new Color(253, 239, 175, 148);
private static final Color clrGlowInnerLo = new Color(255, 209, 0);
private static final Color clrGlowOuterHi = new Color(253, 239, 175, 124);
private static final Color clrGlowOuterLo = new Color(255, 179, 0);
private Shape createClipShape() {
float border = 20.0f;
float x1 = border;
float y1 = border;
float x2 = width - border;
float y2 = height - border;
float adj = 3.0f; //帮助圆化类锐的拐角
float arc = 8.0f;
float dcx = 0.18f * width;
float cx1 = x1-dcx;
float cy1 = 0.40f * height;
float cx2 = x1+dcx;
float cy2 = 0.50f * height;
GeneralPath gp = new GeneralPath();
gp.moveTo(x1-adj, y1+adj);
gp.quadTo(x1, y1, x1+adj, y1);
gp.lineTo(x2-arc, y1);
gp.quadTo(x2, y1, x2, y1+arc);
gp.lineTo(x2, y2-arc);
gp.quadTo(x2, y2, x2-arc, y2);
gp.lineTo(x1+adj, y2);
gp.quadTo(x1, y2, x1, y2-adj);
gp.curveTo(cx2, cy2, cx1, cy1, x1-adj, y1+adj);
gp.closePath();
return gp;
}
private BufferedImage createClipImage(Shape s) {
// 创建一半透明的中间图像,我们可以使用它来实现软修剪效果
GraphicsConfiguration gc = g.getDeviceConfiguration();
BufferedImage img = gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
Graphics2D g2 = img.createGraphics();
//清除图像,这样所有的像素都具有零alpha
g2.setComposite(AlphaComposite.Clear);
g2.fillRect(0, 0, width, height);
// 把我们的修剪形状生成到图像上。注意,我们启动了
// 反走样功能以实现软修剪效果。你可以
//尝试注释掉启动反走样的这一行,那么
//你会看到通常的生硬的修剪效果.
g2.setComposite(AlphaComposite.Src);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.WHITE);
g2.fill(s);
g2.dispose();
return img;
}
private static Color getMixedColor(Color c1, float pct1, Color c2, float pct2) {
float[] clr1 = c1.getComponents(null);
float[] clr2 = c2.getComponents(null);
for (int i = 0; i < clr1.length; i++) {
clr1[i] = (clr1[i] * pct1) + (clr2[i] * pct2);
}
return new Color(clr1[0], clr1[1], clr1[2], clr1[3]);
}
//下面是实现技巧
|