1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
| #include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
using namespace std;
/// <summary>
/// 쉐이더 소스 코드를 입력받아 쉐이더 객체 생성하고 컴파일
/// </summary>
/// <param name="source">쉐이더 소스 코드</param>
/// <param name="type">GL_VERTEX_SHADER 또는 GL_FRAGMENT_SHADER</param>
/// <returns>컴파일된 쉐이더 객체의 ID 또는 0(에러)</returns>
static GLuint CompileShader(GLenum type, const string& source)
{
// 빈 쉐이더 객체 생성
GLuint shaderID = glCreateShader(type);
const char* src = source.c_str();
// 쉐이더 코드를 쉐이더 객체로 변환하여 위의 쉐이더 객체 id에 바인딩
glShaderSource(shaderID, 1, &src, nullptr);
// 쉐이더 컴파일
glCompileShader(shaderID);
// 쉐이더 컴파일 결과 검증
GLint result;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &result);
// 컴파일이 실패한 경우
if (result == GL_FALSE)
{
int length;
// 로그의 길이값을 length에 받아오기
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &length);
// 스택에 배열 동적 할당
char* message = (char*)_malloca(length * sizeof(char));
// 로그 메시지 받아오기
glGetShaderInfoLog(shaderID, length, &length, message);
// 에러 메시지 출력
cout << "Failed to Compile "
<< ((type == GL_VERTEX_SHADER) ? "Vertex" : "Fragment")
<< " Shader"
<< endl;
cout << "\nError Message :" << endl;
cout << message << endl;
// 쉐이더 메모리 해제
glDeleteShader(shaderID);
_freea(message);
return 0;
}
return shaderID;
}
/// <summary>
/// 프로그램, 쉐이더 객체 생성
/// </summary>
/// <param name="vertexShader">버텍스 쉐이더 소스 코드</param>
/// <param name="fragmentShader">프래그먼트 쉐이더 소스 코드</param>
/// <returns>생성된 프로그램 객체의 ID</returns>
static GLuint CreateShader(const string& vertexShader, const string& fragmentShader)
{
// 빈 프로그램 객체 생성
GLuint programID = glCreateProgram();
// 쉐이더 컴파일
GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
// 프로그램에 쉐이더 장착, 프로그램 링킹, 검증
glAttachShader(programID, vs);
glAttachShader(programID, fs);
glLinkProgram(programID);
glValidateProgram(programID);
// 쉐이더 메모리 해제
glDeleteShader(vs);
glDeleteShader(fs);
return programID;
}
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
// glewInit은 rendering context를 만들고 난 이후에 해야 함
if (glewInit() != GLEW_OK)
{
cout << "GLEW INIT ERROR" << endl;
}
// 간단히 GLEW 버전 확인
cout << glGetString(GL_VERSION) << endl;
// Vertex Attribute : 위치 데이터
float positions[6] = {
-0.5f, -0.5f,
0.0f, 0.5f,
0.5f, -0.5f,
};
// VBO(Vertex Buffer Object) ID 생성
GLuint buffer;
// VBO 객체 생성
glGenBuffers(1, &buffer);
// VBO 타입 바인딩
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// VBO에 위치 데이터 연결
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), positions, GL_STATIC_DRAW);
// 정점 속성 정의
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
// 정점 속성 활성화
glEnableVertexAttribArray(0);
// 쉐이더 작성
string vertexShader =
"#version 330 core\n"
"\n"
"layout(location = 0) in vec4 position;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
"}\n";
string fragmentShader =
"#version 330 core\n"
"\n"
"layout(location = 0) out vec4 color;\n"
"\n"
"void main()\n"
"{\n"
" color = vec4(0.2, 0.3, 0.8, 1.0);\n"
"}\n";
// 쉐이더 객체 생성 및 컴파일, 프로그램 객체 생성
GLuint shaderProgram = CreateShader(vertexShader, fragmentShader);
// 쉐이더 프로그램 객체 사용
glUseProgram(shaderProgram);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
// 프로그램 객체 메모리 해제
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
|