2012-09-28 1 views
18

기본적으로 기하학적 모양을 여러 개의 작은 삼각형 ("왼쪽 캔버스")으로 자르고, 삼각형의 무리에 간단한 수학적 변환을 적용하고, 다시 그리는 프로그램을 설계했습니다. 그들의 새로운 구성. 아래 화면 캡처를 참조하십시오. 이 삼각형을 그릴하기 위해Qt/C++ : 효율적으로 그리기

screen cap 1

, 나는 QPainter::drawPolygon를 사용합니다. 오른쪽의 각 삼각형은 왼쪽의 삼각형에 해당하므로 어떤 색으로 그려야하는지 알 수 있습니다.

지금까지는 문제가 없습니다. 이보다 더 많은 삼각형을 그릴지라도 (모양을 자르기 위해 훨씬 작은 삼각형을 사용할 때), 이것은 충분히 빠릅니다.

내 프로그램에 기능을 추가했습니다. 일반 삼각형 대신 그림에서 추출한 삼각형을 그릴 수 있습니다. 다음 화면 캡처를 참조하십시오.

enter image description here

문제는 내가이 작업을 수행하는 방식이 너무 느린 것입니다. 여기에 내가 그것을 할 방법은 다음과 같습니다

나는 모든 삼각형 각 삼각형
  • 를 통해 실행
    1. , 내가 표시됩니다 각 픽셀의 좌표를 계산한다.
    2. 이 픽셀들 각각에 대해 그림에서 해당 픽셀의 좌표를 계산합니다 (이것은 쉬운 수학적 연산입니다). 그리고 그 픽셀의 색을 검색합니다.
    3. 픽셀을 그리는 데 QPainter::setPen(QColor)QPainter::drawPoint(QPoint)을 사용합니다.

    나는 Qt는 프로그래밍에 새로운 오전 나는 그래픽에 대해 아무것도 몰라, 그래서 이것은 내가 가지고 올 수있는 것입니다. 문제는 "받아 들일 수 없을 정도로"너무 느리다는 것입니다 (각 캔버스의 paintEvent은 0.15 초, 일반 삼각형의 경우 0.01 초).

    는 는 내가 무슨 일이 일어나고 있는지 이해하려고 노력하는 프로파일 러를 실행

    , 나는 캔버스 위젯의 paintEvent, 시간의

    1. 58 %의 시간 QPainter::drawPoint
    2. 27 %에 소요되는이 소요되는에 나타났습니다 in QPainter::setPen

    QPainter::drawPoint은 너무 복잡하고 느린 것 같습니다. 나는 단지 주어진 색상의 픽셀을 인쇄하기를 원합니다.

    내 문제에 대한 해결책을 찾았을 수도 있습니다. 내 캔버스에 표시하려는 모든 것을 나타내는 QImage (내 캔버스 위젯의 멤버 변수로)을 저장하고 내 paintEvent 픽셀로 완전히 정의합니다. 내 paintEvent의 끝에 즉시 QPainter::drawImage으로 그립니다. 나는 이것이 훨씬 더 빠를 것이라는 암시를 가지고있다. 하지만 코드를 다시 작성하기 전에 이것이 내가 정말로하고 싶은 것인지를 알고 싶습니다.

    나는 당신이 죽음을 지루하게하지 않았기를 희망합니다! 당신의 통찰에 미리 감사드립니다.

  • +1

    픽셀 단위로 그림을 그리는 중 ?? (zomg !!) – UmNyobe

    답변

    4

    비는 OpenGL 용액 :

    대상 이미지의 RGB 버퍼를 사용한다. 이전처럼 3 단계로 진행하십시오. 위치와 픽셀 색을 찾으면이 버퍼에 설정합니다. 그런 다음 이전 버퍼를 기반으로 이미지를 생성하려면

    QImage::QImage (uchar * data, int width, int height, Format format) 
    

    을 사용하십시오. 을 제공 한 솔루션에 가깝고 현재 가지고있는 것보다 훨씬 빠릅니다.

    +0

    많은 감사합니다!언젠가는 OpenGL에 대해 알기 전까지 이것을 사용할 것입니다. – Seub

    +2

    나는 이것이 내가하는 일을 위해 괜찮음을 확인한다. (최대 0.04 초의 paintEvent) – Seub

    7

    OpenGL은 이미지 (텍스처) 좌표 매핑을 정말 잘합니다. 아마도 OpenGL을 사용하고 싶을 것입니다. Qt는 OpenGL에 바인딩되어있어 당신을 도울 수 있습니다.

    +0

    +1 OP에서 UV 매핑 앱을 만드는 것으로 보입니다. OpenGL은이를위한 완벽한 도구입니다. – cmannett85

    +0

    답변 해 주셔서 감사합니다. 나는 이것을 언젠가 확실히 들여다 볼 것입니다. 문제는 OpenGL에 대해 아무 것도 모른다는 것입니다. – Seub

    3

    이렇게하는 한 가지 방법은 QGraphicsScene/QGraphicsView 콤보 대신 QGLWidget에서 상속 한 클래스를 사용하는 것입니다. 불행하게도 OpenGL의 학습 곡선은 약간 가파르게 시작됩니다. 그러나 이러한 종류의 작업에 최적화 된 그래픽 카드에서 직접 발생하기 때문에 매우 빠릅니다.
    QGLWidget::bindTexture() 이미지를로드합니다.
    이미지의 점을 삼각형 메쉬와 연결하여 그래픽 카드에 모두 보냅니다.

    glEnable(GL_TEXTURE_2D); 
    
    glBegin(GL_TRIANGLES); 
    for (int ii=0;ii<triangle.size();++ii) { 
        for (int jj=0;jj<3;++jj) { 
        glTexCoord2d(triangle[ii].tex[jj][0],triangle[ii].tex[jj][1]); 
        glVertex2d(triangle[ii].point[jj[0],triangle[ii].point[jj][1]); 
        } 
    } 
    glEnd(); 
    

    triangle 당신이 삼각형의 꼭지점을 잡고 제작 한 일부 데이터 구조는 다음과 같습니다 (제 생각에 새로운 API보다 사용하기 쉽다)는 OpenGL의 기존 버전에서는 다음과 같이 보일 것입니다 및 관련 매핑을 이미지에 추가합니다. 그래픽 카드가 픽셀 보간을 처리합니다.

    +0

    답변 해 주셔서 감사합니다. 이것은 매우 흥미 롭습니다. "불행히도 OpenGL의 학습 곡선은 약간 가파르게 시작됩니다." 나는 그것이 나를위한 문제라고 생각한다! 그러나 나는 아마 그것에 대해 어느 시점에서 배워야 할 것이다. – Seub

    +0

    사용되지 않는 코드가 사용됩니다. 정말로 셰이더와 텍스처 샘플러를 사용하고 싶습니다. – doron

    +0

    @doron 더 이상 사용되지 않습니다. 그러나 고정 파이프 라인 기능이 제대로 작동한다면 그렇게하는 것이 훨씬 쉽습니다. GLSL은 3D 프로그래밍 학습의 어려움을 증가시킵니다. 더 많은 유연성을 제공하지만 어셈블리 코드도 그렇습니다. 아직도, 우리 중 대부분이 너무 많은 프로그램을하지 않는 이유가 있습니다. – JCooper

    1

    OpenGL을 제외하고는 OpenCL을 사용하는 것이 더 쉬운 방법입니다. 입출력 비트 맵을 메모리 카드에 그래픽 카드로 매핑하고, C에 하나의 삼각형을 처리하는 작은 커널을 작성한 다음, 각 삼각형에 대해 커널 실행을 대기시켜야합니다. 이것은 CPU의 단일 코어보다 100 배 빠른 속도로 작동합니다.

    여기 OpenCL을 호스트 API를위한 Qt는 래퍼가 :

    http://doc.qt.digia.com/opencl-snapshot/index.html

    0

    다른 접근 방식은 이미 래스터 페인트 엔진 내에서 효율적으로 구현 된 클리핑 및 변환을 활용하는 것입니다. 두 개의 삼각형 사이의 변환이 3x3 증대 된 변환 행렬을 사용하여 표현 될 수 있다면 대상 화가에서 설정 한 다음 대상에 전체 소스 이미지를 그려야합니다. 클리핑되고 대상 삼각형을 채우도록 변형됩니다. 또한 프로파일 링이 장점을 보여주는 경우 전체 이미지 대신 소스 삼각형의 경계 사각형을 그릴 수 있습니다.

    CPU 코어와 동일한 수의 삼각형을 병렬로 처리 할 수 ​​있도록 병렬화 할 수 있습니다.