Opengl Shader Program Disable

300x250

 

쉐이더 프로그램을 종료하기 위해서는  NULL 또는 0으로 값을 넣어서 종료시켜줘야 합니다.

glUseProgram(NULL); 또는 glUseProgram(0);

 

 

아래 여러 예를 들어볼께요.

예제1 ) 단순 프로그램 종료 예시 입니다.

만약 glUseProgramObjectARB을 사용했다면 똑같이 glUseProgramObjectARB로 사용하면 됩니다.

programID = LoadShaders("VertexShader.txt", "FragmentShader.txt");
glUseProgram(programID);
...
...
...
glUseProgram(NULL);

 

예제2) 여러 버퍼를 바인딩한 경우의 예시

프로그램 사용과 VAO 바인딩, 각종 버퍼를 바인딩 한 경우에는 전부 해제해줘야 한다.

programID = LoadShaders("VertexShader.txt", "FragmentShader.txt");
glUseProgram(programID);

glGenVertexArrays(1, &VAO[0]);  // 1.할당 (앞에 인자는 1개 의미)
glBindVertexArray(VAO[0]);

glGenBuffers(1, &VBO[0]);  // 1.할당 (앞에 인자는 1개 의미)
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);

glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

...
...
...
glUseProgram(NULL);
glBindVertexArray(NULL);
glBindBuffer(GL_ARRAY_BUFFER, NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);

 

 

300x250

댓글()

OpenGL 강좌3 - EBO + VAO + VBO

300x250

프로그램 및 코드 다운로드

2. Example_OpenGL_EBO_VAO_VBO.zip
7.74MB

주요 코드는 아래와 같습니다.

#pragma once
#include "GlRender.h"

class RenderEBO_VAO_VBO : public GlRender
{
public:
    RenderEBO_VAO_VBO();
    ~RenderEBO_VAO_VBO();
    
private:
    void GlInit() override;
    void GlDraw() override;

    float vertices[4] = {
        0,10,
        200, 110
    };
    float vertices2[4] = {
        0,20,
        200, 120
    };


    GLuint VAO;
    GLuint VAO2;

    GLuint VBO;
    GLuint VBO2;


    GLuint EBO;
    GLuint VAO3;
    GLuint VBO3;


    float vertices3[12] = {
        50.5f,  50.5f, 0.0f,  // 우측 상단
        50.5f, -50.5f, 0.0f,  // 우측 하단
        -50.5f, -50.5f, 0.0f,  // 좌측 하단
        -50.5f,  50.5f, 0.0f   // 좌측 상단
    };
    unsigned int indices[6] = {  // 0부터 시작한다는 것을 명심하세요!
        0, 1, 3,   // 첫 번째 삼각형
        1, 2, 3    // 두 번째 삼각형
    };

};

 

아래 코드에서는 VAO + VBO를 2개 만들어서 2개의 라인을 그립니다.

그리고 EBO + VAO + VBO를 사용하여 정점 좌표를 인덱싱하여 순서를 변경 합니다.

위에 헤더의 indices를 주목해 주세요.

0~4 사이의 순서를 변경하면 LINE_STRIP 그리는 위치가 바뀌게 됩니다.

void RenderEBO_VAO_VBO::GlInit()
{    
    /***************************************************************************************
    * VAO + VBO 1번째
    **************************************************************************************/
    // VAO 생성 및 바인딩
    glGenVertexArrays(1, &VAO);  // 1.할당 (앞에 인자는 1개 의미)
    glBindVertexArray(VAO);

    // VBO
    // 1. Gen(할당) -> 2. Bind(바인딩) -> 3. Data(입력) -> 4. Link 순서로 사용
    glGenBuffers(1, &VBO);  // 1.할당 (앞에 인자는 1개 의미)
    glBindBuffer(GL_ARRAY_BUFFER, VBO); // 2. GL_ARRAY_BUFFER 형식 바인딩 (이 버퍼 말고도 종류가 많음)
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STREAM_DRAW); // 3.데이터 복사 및 크기 설정
    ///GL_STATIC_DRAW: 데이터가 거의 변하지 않습니다.
    ///GL_DYNAMIC_DRAW: 데이터가 자주 변경됩니다.
    ///GL_STREAM_DRAW: 데이터가 그려질때마다 변경됩니다.

    // 4. Link Vertex Attribute
    int location = 0;
    glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GL_FLOAT), (void*)0);
    glEnableVertexAttribArray(location);



    /***************************************************************************************
    * VAO + VBO 2번째
    **************************************************************************************/
    // VAO 생성 및 바인딩
    glGenVertexArrays(1, &VAO2); // 1.할당 (앞에 인자는 1개 의미)
    glBindVertexArray(VAO2); // VAO를 OpenGL context에 연결(bind)

    // VBO
    // 1. Gen(할당) -> 2. Bind(바인딩) -> 3. Data(입력) -> 4. Link 순서로 사용
    glGenBuffers(1, &VBO2);   // 1.할당 (앞에 인자는 1개 의미)
    glBindBuffer(GL_ARRAY_BUFFER, VBO2); // 2. GL_ARRAY_BUFFER 형식 바인딩 (이 버퍼 말고도 종류가 많음)
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STREAM_DRAW); // 3.데이터 복사 및 크기 설정
    ///GL_STATIC_DRAW: 데이터가 거의 변하지 않습니다.
    ///GL_DYNAMIC_DRAW: 데이터가 자주 변경됩니다.
    ///GL_STREAM_DRAW: 데이터가 그려질때마다 변경됩니다.

    // 4. Link Vertex Attribute
    glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GL_FLOAT), (void*)0);
    glEnableVertexAttribArray(location);



    /***************************************************************************************
     * EVO + VAO + VBO
     **************************************************************************************/
    // VAO 생성 및 바인딩
    glGenVertexArrays(1, &VAO3);  // 1.할당 (앞에 인자는 1개 의미)
    glBindVertexArray(VAO3);  // VAO를 OpenGL context에 연결(bind)

    // VBO
    // 1. Gen(할당) -> 2. Bind(바인딩) -> 3. Data(입력) -> 4. Link 순서로 사용
    glGenBuffers(1, &VBO3);   // 1.할당 (앞에 인자는 1개 의미)
    glBindBuffer(GL_ARRAY_BUFFER, VBO3);  // 2. GL_ARRAY_BUFFER 형식 바인딩 (이 버퍼 말고도 종류가 많음)
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices3), vertices3, GL_STREAM_DRAW); // 3.데이터 복사 및 크기 설정

    // OpenGL이 사용하기 위해 인덱스 리스트를 element 버퍼에 복사
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STREAM_DRAW);
    ///GL_STATIC_DRAW: 데이터가 거의 변하지 않습니다.
    ///GL_DYNAMIC_DRAW: 데이터가 자주 변경됩니다.
    ///GL_STREAM_DRAW: 데이터가 그려질때마다 변경됩니다.

    // Link Vertex Attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
}

 

void RenderEBO_VAO_VBO::GlDraw()
{
    glViewport(0, 0, gl_window_width, gl_window_height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glOrtho((double)-gl_window_width / 2, (double)gl_window_width / 2,
        (double)-gl_window_height / 2, (double)gl_window_height / 2,
        1, -1);
    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0, 0, 0, 0);


    glBindVertexArray(VAO);	// 한 줄로 끝!
    glColor4f(0, 1, 0, 1);
    glDrawArrays(GL_LINES, 0, 2);


    glBindVertexArray(VAO2);	// 한 줄로 끝!
    glColor4f(0, 0, 1, 1);
    glDrawArrays(GL_LINES, 0, 2);


    glBindVertexArray(VAO3);	// 한 줄로 끝!
    glColor4f(0, 0, 1, 1);
    glDrawElements(GL_LINE_STRIP, 6, GL_UNSIGNED_INT, 0); // EBO 사용 시 glDrawElements로 출력
}
300x250

댓글()

OpenGL 강좌2 - VBO (VertexBufferObject)

300x250

프로그램 및 코드 다운로드

1. Example_OpenGL_VBO.zip
7.73MB

 

주요 코드는 아래와 같습니다.

 

Header

class RenderVBO : public GlRender
{
public:
    RenderVBO();
    ~RenderVBO();

    GLuint VBO;

    float vertices[8] = {
        0,10,
        200, 110,
        -0,-10,
        -200,-110
    };


private:
    void GlInit() override;
    void GlDraw() override;
};

 

 

CPP

void RenderVBO::GlInit()
{
    // 1. Gen(할당) -> 2. Bind(바인딩) -> 3. Data(입력) -> 4. Link 순서로 사용

    glGenBuffers(1, &VBO); // 1.할당
    glBindBuffer(GL_ARRAY_BUFFER, VBO); // 2. GL_ARRAY_BUFFER 형식 바인딩 (이 버퍼 말고도 종류가 많음)
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) /* Byte 크기*/ , &vertices[0], GL_STREAM_DRAW); // 3.데이터 복사 및 크기 설정
    ///GL_STATIC_DRAW: 데이터가 거의 변하지 않습니다.
    ///GL_DYNAMIC_DRAW: 데이터가 자주 변경됩니다.
    ///GL_STREAM_DRAW: 데이터가 그려질때마다 변경됩니다.

    // 4. Link Vertex Attribute
    int location = 0;

    // 파라미터 : location, 크기, 데이터 형태(float 등), Normalize 여부, 한점 BYTE 크기 (0이면 자동 계산), 시작 인덱스
    glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GL_FLOAT), (void*)0);
    glEnableVertexAttribArray(0);

}

VBO를 사용하기 위해서는 아래순서로 사용합니다. 꼭 기억해두세요.

1. Gen(할당) -> 2. Bind(바인딩) -> 3. Data(입력) -> 4. Link 순서로 사용

 

 

void RenderVBO::GlDraw()
{
    glViewport(0, 0, gl_window_width, gl_window_height);
    glLoadIdentity();

    glOrtho((double)-gl_window_width / 2, (double)gl_window_width / 2,
        (double)-gl_window_height / 2, (double)gl_window_height / 2,
        1, -1);
    

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0, 0, 0, 0);


    glColor4f(0, 1, 0, 1);

    // 중요! 단독으로 VBO만 사용시 VBO버퍼에 마지막으로 입력된 데이터가 출력됨
    // 만약 여러 데이터를 입력하려면 VAO를 같이 사용해야 함(다음 예제 참조)
    glDrawArrays(GL_LINES, 0, 2); // glBegin(GL_LINES); 처럼 쓰면됨 GL_POINTS 등등
    
}

glDrawArrays로 버퍼에 저장된 데이터를 출력하였습니다.

 

300x250

댓글()

OpenGL 강좌1 - MFC 윈도우창에 띄우기 (32비트, 64비트 설정 포함) 및 예제코드

300x250

 

 

 

 

 

이번 내용은 OpenGL을 윈도우 창과 연동하는 방법을 작성하였습니다.

 

주 내용은 간단합니다.

예제 파일에 있는 GlRender.cpp, GlRender.h 파일을 사용해서 

GlRender클래스는 자체 OpenGLCreate 관련 함수와, 쓰레드 생성 함수들이 있습니다.

나중에 GlStart()를 호출하게되면 MFC 화면에 영상이 출력됩니다.

 

RenderTest라는 클래스를 만들었습니다.

 

 

RenderTest.h

#pragma once
#include "GlRender.h"

class RenderTest : public GlRender
{
public:
    RenderTest();
    ~RenderTest();
    
private:
    void GlInit() override;
    void GlDraw() override;
};

헤더는 GlRender를 상속받습니다.

GlRender 클래스에 가상함수로 호출되기 때문에 GlInit(), GlDraw() 함수는 오버라이드! 

 

RenderTest.cpp

#include "stdafx.h"
#include "RenderTest.h"


RenderTest::RenderTest(){}

RenderTest::~RenderTest(){}

void RenderTest::GlInit(){}

void RenderTest::GlDraw()
{
    glViewport(0, 0, gl_window_width, gl_window_height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glOrtho((double)-gl_window_width / 2, (double)gl_window_width / 2,
        (double)-gl_window_height / 2, (double)gl_window_height / 2,
        1, -1);


    glMatrixMode(GL_MODELVIEW);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0, 0, 0, 0);


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

    glPushMatrix();
    {
        glBegin(GL_LINES);

        glColor4f(0, 1, 0, 1);
        glVertex2d(0, 0);
        glVertex2d(200, 100);

        glEnd();
    }
    glPopMatrix();
    glDisable(GL_BLEND);



    glMatrixMode(GL_MODELVIEW);
    glMatrixMode(GL_PROJECTION);

}

 

RenderTest의 GlDraw() 함수 내용을 보면

중요한 내용은 아니지만 대략적으로 설명을 해보겠습니다.

 

1. glViewport를 사용하여 그릴 화면 영역을 잡고

2. 공간 메트릭스 행렬 초기화

3. glOrtho를 사용하여 화면 Viewport 영역 좌표계를 설정 했습니다.

4. GL_BLEND를 사용하여 투명도 적용

 

GlBegin ~ GlEnd() 내용에 색상을 정하고, 점2개로 직선을 그리는 OpenGL 코드를 작성하였습니다.

 

 

이제 MFC 화면에 연동을 해볼께요

 

0. stdafx.h에 OpenGL 환경설정 추가

#pragma comment ( lib, "OpenGL32.lib" )

#ifdef _WIN32
#include "OpenGL_lib/core/x86/glew.h"
#include "OpenGL_lib/core/x86/wglew.h"
#endif

#ifdef _WIN64
#include "OpenGL_lib/core/x64/glew.h"
#include "OpenGL_lib/core/x64/wglew.h"
#endif

 

1. 먼저 출력할 Dialog 클래스 헤더에 객체 선언

    RenderTest m_render_test;

 

2.  OnInitDialog() 함수에

m_render_test.Create(this);
m_render_test.GlStart();

 

3. OnSize() 함수에

m_render_test.GlResize(cx, cy);

 

4. OnClose() 함수에

m_render_test.GlClose();

 

 

프로그램을 실행한 결과!

 

예시 코드는 아래에서 받을 수 있습니다.

1. Example_OpenGL_MFC.zip
8.23MB

VisualStudio 2012에서 작성되었습니다.

300x250

댓글()