ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • opengl 삼각형 그리기
    3D웹 프로그래밍/opengl 2020. 11. 19. 13:32
    728x90
    반응형

    삼각형 그리기

    Opengl은 많은 프리미티브 타입을 제공한다. 그중에서 점, 선 ,삼각형이 제일 중요하다. 앞의 글에서 한 점을 그릴때 GL_POINTS값을 glDrawArrays()함수에 제공했는데, 이제 선이나 삼각형을 넣어보자.

     

    glDrawArrays()에 GL_LINES나 GL_TRIANGLES를 전달할수있다. 하지만 여기에 한가지 문제가있다.

     

    #version 430 core
    
    void main(void){
    gl_Position =vec4(0.0,0.0,0.5,1.0);
    }

     

     

    위와 같이 그전에 그렸던 버텍스 쉐이더는 모든 버텍스를 같은 위치에 배치한다.

    즉, 클립 공간의 한가운데에 점을 그려도 OpenGL이 그릴 영역을 확보해주므로 별문제가 없다.

    하지만 선이나 삼각형의 경우에는 둘 이상의 버텍스가 동일한 위치에 있으면 프리미티브가 취소된다 왜냐하면

    선의 길이나 삼각형의 면적이 0이 되기 떄문이다. 그러므로 버텍스 쉐이더를 수정하여 각 버텍스에 따라 다른 위치에 그려야한다.

     

    GLSL은 버텍스 쉐이더에 gl_VertexID라는 특별한 입력을 사용할수있다.

    이는 해당 시점에 처리될 버텍스의 인덱스이다. gl_VertexID 입력값은 glDrawArrays()에 입력으로 들어간 첫번째 인자값부터 시작해서 count만큼의 버텍스까지 한 벅테스에 대해 한번에 하나씩 증가한다.

     

    GLSL의 많은 내장 변수중 하나인 gl_VertexID는 opengl에 의해 생성된 데이터지만, 쉐이더에서 생성해서 OpenGL에 넘기는 내장 변수들도 있다.

     

     

     

      //vertex shader 소스
            static const GLchar* vertex_shader_source[] = {
                "#version 430 core\n"
                "\n"
                "void main(void)\n"
                "{\n"
                "const vec4 vertices[3] = vec4[3](vec4(0.25,-0.25,0.5,1.0),vec4(-0.25,-0.25,0.5,1.0),vec4(0.25,0.25,0.5,1.0));"
                "gl_Position = vertices[gl_VertexID]; \n"
                "}"
            };

    위 와같이 gl_VertexID의 값에 기반하여 각 버텍스에 다른 위치를 할당한다.

     

    vertices 배열의 점들은 삼각형을 구성한다. 이제 렌더함수에서 glDrawArrays함수에 GL_TRIANGLES를 넣어주자

     

     

     

     

     

     

     

     

    렌더링

     void render(double currentTime)
        {
             const GLfloat color[] ={ 0.0f , 0.2f, 0.0f,1.0f};
          
            glClearBufferfv(GL_COLOR, 0, color);
    
            //렌더링을 위해 생성했던 프로그램 객체를 사용한다.
            glUseProgram(rendering_program);
    
            //점을 하나 그린다.
            glDrawArrays(GL_TRIANGLES, 0, 3);
        }
    

    삼각형이 잘그려지는것을 확인할수있다.

     

    아래는 풀코드이다.

     

     

     

     

     

    /*
     * Copyright ?2012-2013 Graham Sellers
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the "Software"),
     * to deal in the Software without restriction, including without limitation
     * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     * and/or sell copies of the Software, and to permit persons to whom the
     * Software is furnished to do so, subject to the following conditions:
     *
     * The above copyright notice and this permission notice (including the next
     * paragraph) shall be included in all copies or substantial portions of the
     * Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     * DEALINGS IN THE SOFTWARE.
     */
    
    #include <sb6.h>
    #include <vmath.h>
    class simpleclear_app : public sb6::application
    {
    public:
        virtual void startup() {
    
            rendering_program = compile_shaders();
            glGenVertexArrays(1, &vertex_array_object);
            glBindVertexArray(vertex_array_object);
        }
    
        void shutdown() {
            glDeleteVertexArrays(1, &vertex_array_object);
            glDeleteProgram(rendering_program);
            glDeleteVertexArrays(1, &vertex_array_object);
        }
    
    
    private:
        GLuint rendering_program;
        GLuint vertex_array_object;
    
    
        void init()
        {
            static const char title[] = "Simple Clear";
    
            sb6::application::init();
    
            memcpy(info.title, title, sizeof(title));
        }
    
        virtual void render(double currentTime)
        {
            const GLfloat color[] ={ 0.0f , 0.2f, 0.0f,1.0f};
          
            glClearBufferfv(GL_COLOR, 0, color);
    
            //렌더링을 위해 생성했던 프로그램 객체를 사용한다.
            glUseProgram(rendering_program);
    
            //점을 하나 그린다.
            glDrawArrays(GL_TRIANGLES, 0, 3);
         
        }
    
    
    
        GLuint compile_shaders(void) {
            GLuint vertex_shader;
            GLuint fragment_shader;
            GLuint program;
            
            //vertex shader 소스
            static const char * vertex_shader_source[] = {
                "#version 420 core                                                 \n"
                "                                                                  \n"
                "void main(void)                                                   \n"
                "{                                                                 \n"
                "    const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0),  \n"
                "                                   vec4(-0.25, -0.25, 0.5, 1.0),  \n"
                "                                   vec4( 0.25,  0.25, 0.5, 1.0)); \n"
                "                                                                  \n"
                "    gl_Position = vertices[gl_VertexID];                          \n"
                "}  \n"      
            };
            //fragment shader 소스
            static const char * fragment_shader_source[] = {
                       "#version 420 core                                                 \n"
                "                                                                  \n"
                "out vec4 color;                                                   \n"
                "                                                                  \n"
                "void main(void)                                                   \n"
                "{                                                                 \n"
                "    color = vec4(1.0, 1.0, 1.0, 1.0);                             \n"
                "}                                                                 \n"
            };
            //버텍스 쉐이더를 생성하고 컴파일한다.
            vertex_shader = glCreateShader(GL_VERTEX_SHADER);
            glShaderSource(vertex_shader, 1, vertex_shader_source, NULL);
            glCompileShader(vertex_shader);
    
            //프래그먼트 쉐이더를 생성하고 컴파일하낟.
            fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
            glShaderSource(fragment_shader, 1, fragment_shader_source, NULL);
            glCompileShader(fragment_shader);
    
            //프로그램을 생성하고 쉐이더를 어태치(attach,부착)시키고 링크한다.
            program = glCreateProgram();
            glAttachShader(program, vertex_shader);
            glAttachShader(program, fragment_shader);
            glLinkProgram(program);
    
            glGenVertexArrays(1, &vertex_array_object);
            glBindVertexArray(vertex_array_object);
    
            //이제 프로그램이 쉐이더를 소유하므로 쉐이더를 삭제한다
            glDeleteShader(vertex_shader);
            glDeleteShader(fragment_shader);
    
            return program;
    
    
        }
    };
    
    DECLARE_MAIN(simpleclear_app)
    
    
    728x90
    반응형
Designed by Tistory.