1

저는 Quartz Composer에 적합한 커스텀 지오메트리 라이브러리를 만들고 플러그인에서 오목한 다각형을 그리려하고 있습니다.오목 폴리곤 렌더링을 위해 GL_STENCIL_TEST를 사용합니다.

사용자가 poly2tri 라이브러리를 구현하여 사용자가 삼각 측량을 선택할지 여부를 선택할 수 있지만 프레임 별 다각형 변환 렌더링에는 적합하지 않습니다.

저는 OpenGL의 멍청한 놈입니다. 저는 스텐실 버퍼와 홀수/짝수 연산에 대해서 많이 읽고, 테스트 해 왔지만, 다른 사람들에게는 효과가있는 것처럼 보이는 코드조차도 저에게는 효과적이지 않습니다.

렌더링 컨텍스트는 CGLContextObj이며 NVidia GEForce GT650을 사용하여 MacBook Pro Retina 디스플레이에서 작업하고 있습니다. 나는 모든 설정에 스텐실 버퍼가 없다는 것을 읽었지 만 때때로 그렇게 작동하는 것처럼 보입니다.

동일한 종류의 구성을 가진 누군가가 작동하는 코드를 사용하고 있으며 내 코드를 살펴볼 수 있는지 궁금합니다.

... 아직 명확하지 않습니다 ...

여기에 내 코드가 있습니다 (그 중 하나는 실제로 많은 구성을 테스트 했으므로) 그리고 결과 그림입니다. 사실은 내가 각 다각형을 요구하는 방법으로 실제 렌더링을 넣어 사용하지만, 나는 훨씬 명확하게하기 위해 재 작성 :


EDIT 사실 나는 각 삼각형을 그릴 필요가 있음을 이해

, 스텐실 버퍼의 비트 값을 반전시키기 위해. 그래서 내 코드를 다음에 다시 작성했습니다.

CGLContextObj cgl_ctx = [context CGLContextObj]; 

CGLLockContext(cgl_ctx); 

GLenum       error; 

if(cgl_ctx == NULL) 
    return NO; 


glPushAttrib(GL_ALL_ATTRIB_BITS); 
glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); 



glEnable(GL_BLEND); 
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

glDisable(GL_CULL_FACE); 
glClear(GL_STENCIL_BUFFER_BIT); 
glClearStencil(0); 

glEnable(GL_STENCIL_TEST); 

glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT); 
glStencilFunc(GL_ALWAYS, 1, 1); 
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 

// glColor4d(1., 1., 1., 1.);  ----> does it make sense ? 
glBegin(GL_TRIANGLE_FAN); { 

    for (int i = 1; i < [vertices count] - 1; i++) { 
     // Allways drawing the first vertex 
     glVertex2d([[[vertices objectAtIndex:0] objectAtIndex:0] doubleValue], [[[vertices objectAtIndex:0] objectAtIndex:1] doubleValue]); 

     // Then two others to make a triangle 
     glVertex2d([[[vertices objectAtIndex:i] objectAtIndex:0] doubleValue], [[[vertices objectAtIndex:i] objectAtIndex:1] doubleValue]); 
     glVertex2d([[[vertices objectAtIndex:i+1] objectAtIndex:0] doubleValue], [[[vertices objectAtIndex:i+1] objectAtIndex:1] doubleValue]); 

    } 

} 
glEnd(); 


glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); 
glStencilFunc(GL_EQUAL, 1, 1); 
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 

glColor4d(1., 0., 0., 0.5); 
glBegin(GL_TRIANGLE_FAN); { 
    for (id vertex in vertices) { 
     glVertex2d([[vertex objectAtIndex:0] doubleValue], [[vertex objectAtIndex:1] doubleValue]); 
    } 
    glVertex2d([[[vertices objectAtIndex:0] objectAtIndex:0] doubleValue], [[[vertices objectAtIndex:0] objectAtIndex:1] doubleValue]); 
} 
glEnd(); 


glDisable (GL_STENCIL_TEST); 




glDisable(GL_BLEND); 


glPopClientAttrib(); 
glPopAttrib(); 



if((error = glGetError())) 
    NSLog(@"OpenGL error %04X", error); 

CGLUnlockContext(cgl_ctx); 

return (error ? NO : YES); 

그래도 작동하지 않습니다. 여기 내 결과와 원본 이미지 및 설명에 대한 링크가 있습니다.

http://what-when-how.com/opengl-programming-guide/drawing-filled-concave-polygons-using-the-stencil-buffer-opengl-programming/

Stencil fails

편집 2 :

는 사실, 석영 작곡가 으로 활성화 컨텍스트는 스텐실 버퍼를 구현하지 않습니다. 스텐실 버퍼로 OpenGL에서 직접 렌더링하는 것은 불가능합니다.

답변

1
... 
glClearStencil(0); 
... 

glClearStencil()은 상태 비트를 설정하고 실제로 스텐실 버퍼를 지우지 않습니다.

각 다각형 앞에 glClear(GL_STENCIL_BUFFER_BIT)을 추가해보십시오.

편집 : 이것처럼 :

#include <GL/glut.h> 
#include <glm/glm.hpp> 
#include <glm/gtc/type_ptr.hpp> 
#include <vector> 

std::vector<glm::vec2> pts; 
bool leftHeld = true; 
glm::vec2* dragPt = NULL; 
void mouse(int button, int state, int x, int y) 
{ 
    glm::vec2 pt(x, glutGet(GLUT_WINDOW_HEIGHT) - y); 

    // left mouse button starts dragging a point 
    dragPt = NULL; 
    leftHeld = false; 
    if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) 
    { 
     leftHeld = true; 
     size_t minIdx = 0; 
     for(size_t i = 0; i < pts.size(); ++i) 
     { 
      float newDist = glm::distance(pt, pts[ i ]); 
      float oldDist = glm::distance(pt, pts[ minIdx ]); 
      if(newDist <= oldDist && newDist < 15.0f) 
      { 
       minIdx = i; 
       dragPt = &pts[ minIdx ]; 
      } 
     } 
    } 

    // middle mouse button clears all points 
    if(button == GLUT_MIDDLE_BUTTON && state == GLUT_UP) 
    { 
     pts.clear(); 
    } 

    // right mouse button adds a point 
    if(button == GLUT_RIGHT_BUTTON && state == GLUT_UP) 
    { 
     pts.push_back(pt); 
    } 

    glutPostRedisplay(); 
} 

void motion(int x, int y) 
{ 
    glm::vec2 pt(x, glutGet(GLUT_WINDOW_HEIGHT) - y); 
    if(dragPt && leftHeld) 
    { 
     *dragPt = pt; 
     glutPostRedisplay(); 
    } 
} 

void glLine(const std::vector<glm::vec2>& line, GLenum mode) 
{ 
    glBegin(mode); 
    for(size_t i = 0; i < line.size(); ++i) 
    { 
     glVertex2f(line[i].x, line[i].y); 
    } 
    glEnd(); 
} 

void display() 
{ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    double w = glutGet(GLUT_WINDOW_WIDTH); 
    double h = glutGet(GLUT_WINDOW_HEIGHT); 
    glOrtho(0, w, 0, h, -1, 1); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    // draw polygon 
    glClear(GL_STENCIL_BUFFER_BIT); 
    { 
     // fill stencil buffer 
     glEnable(GL_STENCIL_TEST); 
     glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); 
     glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); 
     glStencilFunc(GL_ALWAYS, 0x1, 0x1); 
     glBegin(GL_TRIANGLES); 
     for(size_t i = 1; i+1 < pts.size(); ++i) 
     { 
      glVertex2fv(glm::value_ptr(pts[ 0 ])); 
      glVertex2fv(glm::value_ptr(pts[ i ])); 
      glVertex2fv(glm::value_ptr(pts[ i+1 ])); 
     } 
     glEnd(); 

     // fill color buffer 
     glColor3ub(0, 128, 0); 
     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 
     glStencilFunc(GL_EQUAL, 0x1, 0x1); 
     glBegin(GL_TRIANGLES); 
     for(size_t i = 1; i+1 < pts.size(); ++i) 
     { 
      glVertex2fv(glm::value_ptr(pts[ 0 ])); 
      glVertex2fv(glm::value_ptr(pts[ i ])); 
      glVertex2fv(glm::value_ptr(pts[ i+1 ])); 
     } 
     glEnd(); 
     glDisable(GL_STENCIL_TEST); 
    } 

    // draw polygon boundary 
    glLineWidth(1); 
    glColor3ub(255, 255, 255); 
    glLine(pts, GL_LINE_LOOP); 

    // draw vertexes 
    glPointSize(9); 
    glColor3ub(255, 0, 0); 
    glLine(pts, GL_POINTS); 

    glutSwapBuffers(); 
} 

int main(int argc, char **argv) 
{ 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE | GLUT_STENCIL); 
    glutInitWindowSize(640, 480); 
    glutCreateWindow("GLUT"); 
    glutMouseFunc(mouse); 
    glutMotionFunc(motion); 
    glutDisplayFunc(display); 
    glutMainLoop(); 
    return 0; 
} 
+0

내가, 내가 대답을 유감 보지 않았다거야 ... "어떻게 ou는 제안이 솔루션은 내가 추측 일을해야하지만 지금은 싸우고 설정 "석영 작곡가 CGLContextObj에서 스텐실 버퍼 ... 그건 ... 스텐실 버퍼에 0 비트가 정상이 아니에요 ... 아닌가요? –

+0

OpenGL Extensions Viewer는 카드에 실제로 스텐실 버퍼에 0 ** 또는 ** 8 비트가 있음을 알려줍니다 ... 픽셀 형식을 재정의하지 않고 8로 설정하는 방법을 관리하고 있습니다. Quartz Composer에서 할 수 없다고 생각하십니까?!?) –