有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在创建小于窗口的PGraphics对象时避免“抗锯齿效应”,然后将其放大到窗口大小?

运行时,程序将在PGraphics对象“g”中显示在P3D环境中渲染的3D球体,该球体通过获取渲染的PGraphics对象并通过主图形上下文(恰好是P2D)中的image()方法显示

该程序的目的是显示窗口大小如何不总是与渲染大小相关。如果你全屏玩Widows98旧游戏,游戏很可能会以480p的速度呈现,因此全屏只会降低每英寸的像素数,并使图像看起来模糊。这很好,因为480p的全屏模式比窗口模式更受欢迎(尤其是在4K X_X上)

鼠标在窗口中的y位置会更改三维摄影机的视野,x位置会更改用于显示球体的P3D上下文的渲染分辨率。此外,P3D上下文通过image()方法在主(P2D)上下文中绘制,并且是“强制”的。以窗口大小显示。因此,如果P3D渲染分辨率小于窗口,则它将开始看起来模糊且更像素化,如果渲染分辨率更大,则会获得奇怪的锐化效果

现在,我的程序运行正常,但是。该程序的另一个目的被这个问题掩盖了,它是如何随着渲染分辨率的降低而减弱球体的“清晰度”。你可能会说它显示得很清楚,但我要找的是一个没有“反别名”效果的图像。我希望图像在分辨率变小时保留像素,这样你就可以看到球体的实际形状,比如说,50 x 50像素

noSmooth()方法似乎不起作用,在你告诉我怎么做之前

g.loadPixels();

然后执行双for循环,将原始像素绘制到2d上下文中。不,它很邋遢。我知道这种模糊现象一定是有原因的。我希望这是image()方法,我应该使用另一种方法,或者在它之前添加另一种方法来消除图像模糊

PGraphics g;

void setup(){
  size(1000,1000,P2D);
  frameRate(1000);
  noSmooth();
}

void draw(){
  background(200);
  float res = map(mouseX,0,width,0.75,128);
  if (res==0) {
    res=1;
  }

  g = createGraphics((int)(width/res),(int)(height/res),P3D);
  g.noSmooth(); // is this thing working?????
  float cameraZ = ((height/2.0) / tan(PI*60.0/360.0));

  g.beginDraw();
    g.perspective(radians(map(mouseY,0,height,0.1,160)), width/height, cameraZ/10.0, cameraZ*10.0);
    g.camera(g.width/2.0, g.height/2.0, (height/2.0) / tan(PI*30.0 / 180.0), g.width/2.0, g.height/2.0, 0, 0, 1, 0);

    g.background(200);
    g.translate(g.width/2 ,g.height/2);
    g.sphere(100);
  g.endDraw();

  image(g, 0, 0, width, height); // this is where it all comes together
  text("rendering resolution: "+g.width+" x "+g.height,0,14);
  text("fps: "+frameRate,0,14*2);
}

共 (2) 个答案

  1. # 1 楼答案

    编辑:此解决方案修复了默认渲染器中的问题,但OP使用的是P2D渲染器。解决方案应该类似,因此如果有人知道如何在opengl中更改图像插值模式,这就是答案。)

    这实际上不是由抗锯齿引起的。这是由image scaling引起的

    此外,如果提供MCVE,帮助也会容易得多,如下所示:

    PGraphics buffer;
    
    void setup() {
    
      size(1000, 1000);
    
      buffer = createGraphics(100, 100);
      buffer.noSmooth();
      buffer.beginDraw();
      buffer.background(255);
      buffer.line(0, 0, width, height);
      buffer.endDraw();
    }
    
    void draw() {    
      background(0);
      image(buffer, 0, 0, mouseX, mouseY);
    }
    

    这段代码也有同样的问题,但更容易理解和使用

    blurry image

    无论如何,通过Processing's code跟踪,我们可以看到image()函数最终调用了PGraphicshere中的imageImpl()函数

    然后,此函数使用以下代码绘制图像:

    beginShape(QUADS);
    texture(img);
    vertex(x1, y1, u1, v1);
    vertex(x1, y2, u1, v2);
    vertex(x2, y2, u2, v2);
    vertex(x2, y1, u2, v1);
    endShape();
    

    然后在呈现器中实现endShape()函数,特别是PGraphicsJava2D类,它调用drawShape()函数here

    protected void drawShape(Shape s) {
        if (fillGradient) {
          g2.setPaint(fillGradientObject);
          g2.fill(s);
        } else if (fill) {
          g2.setColor(fillColorObject);
          g2.fill(s);
        }
        if (strokeGradient) {
          g2.setPaint(strokeGradientObject);
          g2.draw(s);
        } else if (stroke) {
          g2.setColor(strokeColorObject);
          g2.draw(s);
        }
    }
    

    最后,这向我们展示了正在调用Graphics2D.fill()函数,这就是实际绘制函数的地方

    “问题”是Graphics2D.fill()正在使用一种会导致模糊的算法缩放图像。不过,我们可以咨询the Java API和谷歌,找出如何解决这个问题

    具体来说,this tutorial向您展示了如何设置各种渲染提示以更改缩放算法。我们可以在这样的处理中使用:

    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import processing.awt.PGraphicsJava2D;
    
    PGraphics buffer;
    
    void setup() {
    
      size(1000, 1000);
    
      buffer = createGraphics(100, 100);
      buffer.noSmooth();
      buffer.beginDraw();
      buffer.background(255);
      buffer.line(0, 0, width, height);
      buffer.endDraw();
    }
    
    void draw() {
    
      if (mousePressed) {
        Graphics2D g2d = ((PGraphicsJava2D)g).g2;
    
        g2d.setRenderingHint(
          RenderingHints.KEY_INTERPOLATION, 
          RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
      }
    
      background(0);
      image(buffer, 0, 0, mouseX, mouseY);
    }
    

    首先,我们导入我们需要的类。然后我们进入渲染器中的Graphics2D实例,最后调用它的setRenderingHint()函数。我用一个if(mousePressed)包装了它,这样你就可以很容易地看到区别了。单击鼠标时,“插值”设置为“最近邻”,您将不再看到模糊

    clear image

    还要注意,我的代码使用了从PApplet超类继承的g变量,因此您必须更改g变量,使其不再隐藏

  2. # 2 楼答案

    g.noSmooth()替换为((PGraphicsOpenGL)g).textureSampling(2);

    积分归Vallentin因为我奇怪地对P3D渲染器有同样的问题