使用Java 2D的抗锯齿高度贴图边缘

使用Java 2D的抗锯齿高度贴图边缘,java,rendering,java-2d,antialiasing,terrain,Java,Rendering,Java 2d,Antialiasing,Terrain,我正在使用Java2D渲染地形图。地形图如下所示: 你可以看到边缘是多么的参差不齐。我希望平滑地渲染地形的边缘,但是使用RenderingHints启用抗锯齿功能不起作用,因为我一次渲染一列地形地图 以下是渲染地形的代码: // terrainImageG2 renders to a BufferedImage, obtained via BufferedImage.createGraphics() terrainImageG2.setBackground(Color.WHITE); terr

我正在使用Java2D渲染地形图。地形图如下所示:

你可以看到边缘是多么的参差不齐。我希望平滑地渲染地形的边缘,但是使用
RenderingHints
启用抗锯齿功能不起作用,因为我一次渲染一列地形地图

以下是渲染地形的代码:

// terrainImageG2 renders to a BufferedImage, obtained via BufferedImage.createGraphics()
terrainImageG2.setBackground(Color.WHITE);
terrainImageG2.clearRect(0, 0, NUM_WIDE, NUM_HIGH);
terrainImageG2.setStroke(new BasicStroke(1.0F));
terrainImageG2.setColor(Color.BLACK);
for (int x = 0; x < NUM_WIDE; x++) {
    terrainImageG2.drawLine(x, NUM_HIGH - originalHeightMap[x], x, NUM_HIGH);
    // originalHeightMap contains the height map, ranging from 0 to NUM_HIGH
    // originalHeightMap 
}
实际上,它不会对边缘进行反锯齿。如果启用RenderingHits的抗锯齿,则地形看起来是这样的:

我尝试了一些手动消除混叠,我将顶部像素渲染为浅灰色,而不是黑色。然而,这使得平坦的区域看起来模糊,而不影响陡峭的区域。看一看:

有什么方法可以让我手工或通过API平滑地绘制这条边吗?谢谢

一些想法:

  • 通过将每条线的顶点连接到相邻线的顶点,在顶部绘制一条抗锯齿线。这可能更容易调试,只需绘制顶线以查看其外观,然后填充垂直线(如果您喜欢其外观)

  • 在绘制此图像时,请考虑上一个图像和下一个图像顶部的位置,尝试制定一些类似于抗锯齿工作方式的算法。因此,如果当前值低于或高于之前和之后的值,则在顶部添加一个灰点。如果相同,则不添加点。根据相邻圆点的高度,使圆点变亮或变暗

  • 打印前,使用线性平均或某种曲线平滑来平滑数据。这并不是真正的反别名,但可能会使图形更具吸引力

    • 一些想法:

      • 通过将每条线的顶点连接到相邻线的顶点,在顶部绘制一条抗锯齿线。这可能更容易调试,只需绘制顶线以查看其外观,然后填充垂直线(如果您喜欢其外观)

      • 在绘制此图像时,请考虑上一个图像和下一个图像顶部的位置,尝试制定一些类似于抗锯齿工作方式的算法。因此,如果当前值低于或高于之前和之后的值,则在顶部添加一个灰点。如果相同,则不添加点。根据相邻圆点的高度,使圆点变亮或变暗

      • 打印前,使用线性平均或某种曲线平滑来平滑数据。这并不是真正的反别名,但可能会使图形更具吸引力


      您可以尝试使用其他一些渲染提示

      import java.awt.BasicStroke;
      import java.awt.BorderLayout;
      import java.awt.Color;
      import java.awt.Dimension;
      import java.awt.EventQueue;
      import java.awt.Graphics;
      import java.awt.Graphics2D;
      import java.awt.RenderingHints;
      import javax.swing.JFrame;
      import javax.swing.JPanel;
      import javax.swing.UIManager;
      import javax.swing.UnsupportedLookAndFeelException;
      
      public class TestPaint20 {
      
          public static void main(String[] args) {
              new TestPaint20();
          }
      
          public TestPaint20() {
              EventQueue.invokeLater(new Runnable() {
                  @Override
                  public void run() {
                      try {
                          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                      } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                      }
      
                      JFrame frame = new JFrame("Testing");
                      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                      frame.setLayout(new BorderLayout());
                      frame.add(new TestPane());
                      frame.pack();
                      frame.setLocationRelativeTo(null);
                      frame.setVisible(true);
                  }
              });
          }
      
          public class TestPane extends JPanel {
      
              public TestPane() {
              }
      
              @Override
              public Dimension getPreferredSize() {
                  return new Dimension(200, 200);
              }
      
              @Override
              protected void paintComponent(Graphics g) {
                  super.paintComponent(g);
                  Graphics2D g2d = (Graphics2D) g.create();
                  g2d.setBackground(Color.WHITE);
                  g2d.setStroke(new BasicStroke(1.0F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
                  g2d.setColor(Color.BLACK);
                  g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
                  g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                  g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
                  g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
                  g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
                  g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                  g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                  g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
      
                  for (int x = 0; x < getWidth(); x++) {
                      g2d.drawLine(x, getHeight() - (int) Math.round(Math.random() * (getHeight() - (getHeight() / 4d))), x, getHeight());
                      // originalHeightMap contains the height map, ranging from 0 to NUM_HIGH
                      // originalHeightMap 
                  }
                  g2d.dispose();
              }
          }
      }
      

      import java.awt.BasicStroke;
      导入java.awt.BorderLayout;
      导入java.awt.Color;
      导入java.awt.Dimension;
      导入java.awt.EventQueue;
      导入java.awt.Graphics;
      导入java.awt.Graphics2D;
      导入java.awt.RenderingHints;
      导入javax.swing.JFrame;
      导入javax.swing.JPanel;
      导入javax.swing.UIManager;
      导入javax.swing.UnsupportedLookAndFeelException;
      公共类测试20{
      公共静态void main(字符串[]args){
      新的TestPaint20();
      }
      公共测试20(){
      invokeLater(新的Runnable(){
      @凌驾
      公开募捐{
      试一试{
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      }catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
      }
      JFrame=新JFrame(“测试”);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setLayout(新的BorderLayout());
      frame.add(newtestpane());
      frame.pack();
      frame.setLocationRelativeTo(空);
      frame.setVisible(true);
      }
      });
      }
      公共类TestPane扩展了JPanel{
      公共测试窗格(){
      }
      @凌驾
      公共维度getPreferredSize(){
      返回新维度(200200);
      }
      @凌驾
      受保护组件(图形g){
      超级组件(g);
      Graphics2D g2d=(Graphics2D)g.create();
      g2d.立根背景(颜色:白色);
      g2d.设定行程(新的基本行程(1.0F,基本行程.CAP_ROUND,基本行程.JOIN_ROUND));
      g2d.setColor(Color.BLACK);
      g2d.setRenderingHint(RenderingHits.KEY\u ALPHA\u插值,RenderingHits.VALUE\u ALPHA\u插值\u质量);
      g2d.setRenderingHint(renderingHits.KEY\u抗锯齿,renderingHits.VALUE\u抗锯齿\u开启);
      g2d.setRenderingHint(RenderingHints.KEY\u COLOR\u RENDERING,RenderingHints.VALUE\u COLOR\u RENDER\u QUALITY);
      g2d.setRenderingHint(renderingHits.KEY\u抖动,renderingHits.VALUE\u抖动\u启用);
      g2d.setRenderingHint(renderingHits.KEY_分数矩阵,renderingHits.VALUE_分数矩阵开);
      g2d.setRenderingHint(RenderingHits.KEY\u插值,RenderingHits.VALUE\u插值\u双线性);
      g2d.setRenderingHint(renderingHits.KEY_RENDERING,renderingHits.VALUE_RENDER_QUALITY);
      g2d.setRenderingHint(renderingHits.KEY\u STROKE\u控件,renderingHits.VALUE\u STROKE\u PURE);
      对于(int x=0;x
      您可以尝试使用其他一些渲染提示

      import java.awt.BasicStroke;
      import java.awt.BorderLayout;
      import java.awt.Color;
      import java.awt.Dimension;
      import java.awt.EventQueue;
      import java.awt.Graphics;
      import java.awt.Graphics2D;
      import java.awt.RenderingHints;
      import javax.swing.JFrame;
      import javax.swing.JPanel;
      import javax.swing.UIManager;
      import javax.swing.UnsupportedLookAndFeelException;
      
      public class TestPaint20 {
      
          public static void main(String[] args) {
              new TestPaint20();
          }
      
          public TestPaint20() {
              EventQueue.invokeLater(new Runnable() {
                  @Override
                  public void run() {
                      try {
                          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                      } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                      }
      
                      JFrame frame = new JFrame("Testing");
                      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                      frame.setLayout(new BorderLayout());
                      frame.add(new TestPane());
                      frame.pack();
                      frame.setLocationRelativeTo(null);
                      frame.setVisible(true);
                  }
              });
          }
      
          public class TestPane extends JPanel {
      
              public TestPane() {
              }
      
              @Override
              public Dimension getPreferredSize() {
                  return new Dimension(200, 200);
              }
      
              @Override
              protected void paintComponent(Graphics g) {
                  super.paintComponent(g);
                  Graphics2D g2d = (Graphics2D) g.create();
                  g2d.setBackground(Color.WHITE);
                  g2d.setStroke(new BasicStroke(1.0F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
                  g2d.setColor(Color.BLACK);
                  g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
                  g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                  g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
                  g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
                  g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
                  g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                  g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                  g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
      
                  for (int x = 0; x < getWidth(); x++) {
                      g2d.drawLine(x, getHeight() - (int) Math.round(Math.random() * (getHeight() - (getHeight() / 4d))), x, getHeight());
                      // originalHeightMap contains the height map, ranging from 0 to NUM_HIGH
                      // originalHeightMap 
                  }
                  g2d.dispose();
              }
          }
      }
      

      import java.awt.BasicStroke;
      导入java.awt.BorderLayout;
      导入java.awt.Color;
      导入java.awt.Dimension;
      导入java.awt.EventQueue;
      导入java.awt.Graphics;
      导入java.awt.Graphics2D;
      导入java.awt.Rendering