2017-01-19 7 views
1

내 궁극적 인 목표는 버퍼에 rect를 그리고 다른 버퍼에 버퍼를 복사하고 이후 draw(), copy 두 번째 버퍼가 첫 번째 버퍼로 돌아가고, 약간 작아지며, 그 위에 다시 그립니다.PGraphics는 주 문맥에 그려 질 때마다 지워지거나 얼려진 것처럼 보입니다

나는 여기서 무슨 일이 일어나고 있는지 완전히 이해하기가 어렵습니다.

첫째, 예상 1 시간으로 정확히 작동이 코드, (아무 무승부 루프) 고려 :

PGraphics canvas; 
PGraphics buffer; 

void setup(){ 
    size(500, 500); 
    canvas = createGraphics(width, height); 
    buffer = createGraphics(canvas.width, canvas.height); 

    canvas.beginDraw(); 
    canvas.background(255); 
    canvas.noFill(); 
    canvas.stroke(0); 
    canvas.rect(100 + random(-50, 50), 100 + random(-50, 50), 350 + random(-50, 50), 350 + random(-50, 50)); 
    canvas.endDraw(); 

    buffer.beginDraw(); 
    buffer.image(canvas, 0, 0); 
    buffer.endDraw(); 

    canvas.beginDraw(); 
    canvas.image(buffer, 100, 100, width-200, height-200); 
    canvas.endDraw(); 

    image(canvas, 0, 0); 

    noLoop(); 
} 

그것은 아주 바보 같은 예는,하지만이 개념은 소리임을 증명 : 나는 그릴을 canvas, buffer에 복사하고 buffercanvas으로 다시 축소 한 다음 주 컨텍스트로 출력하십시오.

하지만 추첨에서이 작업을 수행 할 때 발생하는 볼() 루프 : 여기

PGraphics canvas; 
PGraphics buffer; 

void setup(){ 
    size(500, 500); 
    canvas = createGraphics(width, height); 
    buffer = createGraphics(canvas.width, canvas.height); 

    canvas.beginDraw(); 
    canvas.background(255); 
    canvas.noFill(); 
    canvas.stroke(0); 
    canvas.rect(100 + random(-50, 50), 100 + random(-50, 50), 350 + random(-50, 50), 350 + random(-50, 50)); 
    canvas.endDraw(); 

    buffer.beginDraw(); 
    buffer.image(canvas, 0, 0); 
    buffer.endDraw(); 
} 

void draw(){ 
    canvas.beginDraw(); 
    canvas.image(buffer, 0, 0); 
    canvas.rect(100 + random(-50, 50), 100 + random(-50, 50), 350 + random(-50, 50), 350 + random(-50, 50)); 
    canvas.endDraw(); 

    image(canvas, 0, 0); 

    buffer.beginDraw(); 
    buffer.image(canvas, 0, 0); 
    buffer.endDraw(); 
} 

, 일이 끝나는 무슨 일이() 설정에서 만든 원래 RECT 모든 프레임을 복사됩니다 있다는 것입니다 ~ canvas. 그래서 효과는 움직이지 않는 rect와 프레임마다 그려지고 대체되는 두 번째 rect입니다.

더 이상해진다. 단순히 주요 상황에 그리는 image() 기능을 이동할 때 발생하는 시계 :

PGraphics canvas; 
PGraphics buffer; 

void setup(){ 
    size(500, 500); 
    canvas = createGraphics(width, height); 
    buffer = createGraphics(canvas.width, canvas.height); 

    canvas.beginDraw(); 
    canvas.background(255); 
    canvas.noFill(); 
    canvas.stroke(0); 
    canvas.rect(100 + random(-50, 50), 100 + random(-50, 50), 350 + random(-50, 50), 350 + random(-50, 50)); 
    canvas.endDraw(); 

    buffer.beginDraw(); 
    buffer.image(canvas, 0, 0); 
    buffer.endDraw(); 
} 

void draw(){ 
    canvas.beginDraw(); 
    canvas.image(buffer, 0, 0); 
    canvas.rect(100 + random(-50, 50), 100 + random(-50, 50), 350 + random(-50, 50), 350 + random(-50, 50)); 
    canvas.endDraw(); 

    buffer.beginDraw(); 
    buffer.image(canvas, 0, 0); 
    buffer.endDraw(); 

    image(canvas, 0, 0); 
} 

이 일을 변경해야하지 않는다, 그럼에도 불구하고 결과는 이미지가 화면에 두의 구형에 "정지"는 것이다. 웬일인지 canvas가 매번 다시 쓰여지고 있지만 똑같은 것을 반복해서 그려주는 것처럼 보입니다. 대신

image(buffer, 0, 0); 

를 읽고 마지막 라인을 변경

는 "동결"버퍼지만, 그 위에 모든 시간이 지남에 따라 새로운 RECT 그리기 이전 동작으로 돌아 간다.

어떤 일이 일어나고 있는지 알 수 있습니까?

+0

'image()'를'set (0, 0, buffer)'로 바꾸면 문제가 해결되지만 내 질문에는 답하지 않습니다. 여전히 궁금한'image()'가 문서화되지 않은 것에 대해 궁금해 할 것입니다 ... –

답변

0

출처를 살펴보면, 문제는 image()입니다. image()imageImpl()을 호출하여 PGraphics 텍스처를 설정하며 PGraphics에서 재정의됩니다. 텍스처를 설정하는 대신 픽셀을 직접 설정하지 않고 텍스쳐 참조를 유지하고 캐싱합니다. 적어도 호기심을 만족시키기 위해 최소한 PGraphics.image()을 사용하는 이유는 (적어도 메인 드로잉 컨텍스트에서는) 버퍼 PGraphics 객체를 후속 draw() 작업에 쓸모가없는 지점에 "잠급니다".

이러한 문제가 발생하지 않도록 두 가지 해결책이 있습니다

  1. 하지만 이미지에 버퍼를 쓸 수하기 위해 canvas.image()을 계속 사용 (내 예 canvasbuffer에서)이 오프 스크린 버퍼를 사용하여 아마도 그것을 확장 할 수있다. 캔버스를 주 도면 컨텍스트에 쓰는 측면에서는 set(x, y, canvas)을 대신 사용하십시오. PGraphics.set()PImage.set()에서 상속되며 오버라이드되지 않으며 픽셀을 픽셀 단위로 직접 설정하므로 원본 개체에 대한 참조가 없습니다. 또한 텍스처를 그리지 않기 때문에 Java2D 컨텍스트에서 더 빠릅니다 (GL 컨텍스트에서는 느려질 수도 있음).

  2. (적어도 내 경우에는) 다른 옵션은, 전부 canvas 객체를 무시하고, 대신의 전체 복사본을 포함하는 새 PImage 객체를 반환 g.copy()를 사용하여 주요 도면 문맥의 픽셀로 직접 작업하는 것입니다 기본 도면 캔버스 (g은 실제로는 this.g 또는 PApplet.g, 모든 그림 기능이 영향을주는 주요 PGraphics 컨텍스트)입니다. 이것은 PGraphics 객체가 아닌 픽셀의 복사본이기 때문에 함수에서 허용하는 크기 조정을 이용하여 image()을 사용할 수 있습니다.

다음은 몇 가지 예입니다 :

PGraphics canvas; 
PGraphics buffer; 

void setup(){ 
    size(500, 500); 
    canvas = createGraphics(width, height); 
    buffer = createGraphics(canvas.width, canvas.height); 

    canvas.beginDraw(); 
    canvas.background(255); 
    canvas.noFill(); 
    canvas.stroke(0); 
    canvas.rect(100 + random(-50, 50), 100 + random(-50, 50), 350 + random(-50, 50), 350 + random(-50, 50)); 
    canvas.endDraw(); 

    buffer.beginDraw(); 
    buffer.image(canvas, 0, 0); 
    buffer.endDraw(); 
} 

void draw(){ 
    canvas.beginDraw(); 
    canvas.background(255); 
    canvas.image(buffer, 10, 20, width-20, width-20); 
    canvas.rect(100 + random(-50, 50), 100 + random(-50, 50), 350 + random(-50, 50), 350 + random(-50, 50)); 
    canvas.endDraw(); 

    set(0, 0, canvas); 

    buffer.beginDraw(); 
    buffer.image(canvas, 0, 0); 
    buffer.endDraw(); 
} 

위는 "두 버퍼"버전입니다. image() 대신 set()을 사용하십시오. 원래의 예제와 다른 점은 image()에 스케일링을 적용하여 처음부터 찾고 있던 "워프"효과를 얻는 것입니다.

이 (훨씬 짧은) 예는 하나의 오프 스크린 버퍼 복사 주 도면 문맥의 PGraphics이 g.copy()를 통해 개체를 사용하여 두 번째 :

PImage buffer; 

void setup(){ 
    size(500, 500); 

    background(255); 
    noFill(); 
    stroke(0); 

    buffer = g.copy(); 

} 

void draw(){ 
    background(255); 
    image(buffer, 10, 20, width-20, width-20); 
    rect(100 + random(-50, 50), 100 + random(-50, 50), 350 + random(-50, 50), 350 + random(-50, 50)); 

    buffer = g.copy(); 
} 

내가 크게 두 가지 이유, 후자를 선호 하나를, 그것의 명백하게 코드가 적고 메모리가 줄어들 기 때문에 성능이 더 좋아야한다. (나는이 가설을 테스트하지 않았다.) 두 가지면에서, 더 깔끔하고 관용적 인 메인 드로잉 컨텍스트를 계속 사용할 수 있으며, beginDraw() 및 오프 스크린 버퍼의 이름 앞에 모든 그래픽 호출을 다시 작성하지 않고 기존 스케치에이 기술을 적용하십시오.

0

PGraphics 이미지에 정확히 무엇을 가지고 있는지 생각해보십시오.

PGraphics은 흰색 배경과 검은 색 사각형이있는 500x500 이미지입니다.

그런 다음 한 이미지를 가져 와서 다른 이미지를 덮어 씁니다. 그것들은 여전히 ​​검정색 사각형이있는 흰색 이미지입니다. 주의해야 할 중요한 점은 둘 다 흰색 배경을 가지고 있기 때문에 새로운 "통해"오래된 이미지를 볼 수 없습니다. 그래서 여러분은 똑같은 사각형을 앞뒤로 칠하고있는 것입니다.

두 번째 코드 블록에서 canvas.background()에 대한 호출을 제거하면이 사실을 입증 할 수 있습니다. 그러면 직사각형이 서로 겹쳐서 보입니다. 매번 똑같은 사각형을 그려야하기 때문에 여전히 터널링 효과가 아닙니다.하지만 이것은 별개의 문제입니다.

문제를 해결하려면 각 이미지의 내용을 정확히 알아야합니다. 특히 배경이 투명한지 여부에주의하십시오.

주 캔버스에서 같은 작업을 수행하면 버퍼 이미지가 작아 지거나 버퍼 이미지가 전혀없는 단일 버퍼 이미지만으로이 효과를 얻을 수 있습니다.

+0

안녕하세요, Kevin, 답변 해 주셔서 감사합니다.하지만 당신은 똑같은 방식으로 보지 않을 것이라고 생각합니다.불투명 한 흰색 배경에서 시작하여 그 위에 직사각형을 그립니다. 그런 다음 그 전체 (불투명) 이미지를 가져 와서 복사하십시오. 그런 다음 원본 캔버스를 "지우고"사본을 조금 더 작게 만듭니다. 이제 당신은 흰색 배경과 (더 작은) 검은 색 사각형을 가지고 있습니다. 그 다음에 새로운 (더 큰) rect를 그린다. 이제 2 개의 rect를 가져야합니다. 그런 다음 버퍼에 복사하고 캔버스를 지우고 반복합니다. 그래, 이론은 효과가있다. 설명서가 말하는 것보다 더 많은 것을하고있는 것은'image()'입니다. 나는 무엇을 찾으려고 노력하고 있습니다. –

+0

@TomAuger ** 당신이 ** 시도하고있는 ** 것을 이해합니다. 그러나 그것은 당신이 현실에서하는 것이 아닙니다. 내가 무슨 뜻인지 알기 위해'canvas.background()'를 제거해보십시오. 실제로 사각형을 작게 그리지 않는다는 것을 알 수 있습니다. 당신은 단지 무작위 좌표로 그리지 만 그보다 작지는 않습니다. 당신의 코드는 내가 기대했던 것과 정확히 똑같이 행동하기 때문에'image()'가 뭔가 잘못하고있는 것은 아닙니다. –

+0

추가 의견을 보내 주셔서 감사합니다. 위에 나열된 3 가지 예제를 실행 해 보셨습니까? 두 번째와 세 번째 예제에서 버퍼를 캔버스로 복사하는 방법에 대해 메모 해두기 전에 그 위에 그립니다. 그래서 예, 버퍼가 불투명 한 흰색 배경 + 1 rect로 캔버스를 "clobbers"하지만, 다음에는 두 번째 rect를 TOP에 그립니다. 그런 다음 버퍼에 복사하고 반복합니다. 두 번째 반복에서는 (버퍼에서) 불투명 한 bg + 2 사각형으로 캔버스를 clobber하고 위에 세 번째 사각형을 그리고 그 위에 간다. 흥미 롭습니다. image()를 set()으로 대체하면 모든 것이 광고 된대로 작동합니다. –