<basic.vert>

1
2
3
4
5
6
7
8
9
10
11
12
#version 400
in vec3 VertexPosition;
in vec3 VertexColor;
out vec3 Color;
 
uniform mat4 MVP;
 
void main()
{
    Color = VertexColor;
    gl_Position = MVP * vec4(VertexPosition, 1.0);
}
cs

 

 

<basic.frag>

1
2
3
4
5
6
7
#version 400
in vec3 Color;
out vec4 FragColor;
void main() {
    FragColor = vec4(Color, 1.0);
}
 
cs

 

 

<main.cpp>

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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
#include <iostream>
#include <fstream>
 
// glew.h는 gl.h를 포함하기 전에 포함해야한다.
#include "GL/glew.h"
#include "GL/freeglut.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
 
 
// 원하는 프레임 값
#define FPS 30
 
#define X_AXIS glm::vec3(1,0,0)
#define Y_AXIS glm::vec3(0,1,0)
#define Z_AXIS glm::vec3(0,0,1)
#define XY_AXIS glm::vec3(1,0.9,0)
#define YZ_AXIS glm::vec3(0,1,1)
#define XZ_AXIS glm::vec3(1,0,1)
 
GLuint vaoHandle;
GLuint programHandle;
GLuint mvpId;
glm::mat4 MVP, View, Projection;
GLuint setShader(const char* shaderType, const char* shaderName);
char* loadShaderAsString(std::string fileName);
 
float angle = 0.0f;
 
void timer(int); // Prototype.
 
void init()
{
 
    // 1. 쉐이더 오브젝트를 생성한다.
    GLuint vertShader = setShader("vertex""basic.vert");
    GLuint fragShader = setShader("fragment""basic.frag");
 
    // 오브젝트 컴파일이 끝나면 OpenGL pipeline에 컴파일이 끝난 쉐이더를 등록 혹은 설치해야한다.
 
    // 1. 먼저 Program object를 생성한다.
    // 빈 프로그램 생성
    programHandle = glCreateProgram();
    if (0 == programHandle)
    {
        fprintf(stderr, "Error creating program object.\n");
        exit(1);
    }
 
    // 2. 쉐이더들을 프로그램에 붙인다.
    glAttachShader(programHandle, vertShader);
    glAttachShader(programHandle, fragShader);
 
    // 3. 프로그램을 링크한다. 연결
    glLinkProgram(programHandle);
 
    // 4. 링크 상태 확인
    GLint status;
    glGetProgramiv(programHandle, GL_LINK_STATUS, &status);
    if (GL_FALSE == status) {
        fprintf(stderr, "Failed to link shader program!\n");
        GLint logLen;
        glGetProgramiv(programHandle, GL_INFO_LOG_LENGTH,
            &logLen);
        if (logLen > 0)
        {
            char* log = (char*)malloc(logLen);
            GLsizei written;
            glGetProgramInfoLog(programHandle, logLen,
                &written, log);
            fprintf(stderr, "Program log: \n%s", log);
            free(log);
        }
    }
    // 5. 만약 링크가 성공했다면 프로그램을 OpenGL pipeline에 설치 한다.
    else
    {
        glUseProgram(programHandle);
    }
 
    // uniform 사용
    mvpId = glGetUniformLocation(programHandle, "MVP");
 
 
    // vertex의 꼭직점.
    float positionData[] = {
    -0.8f, -0.8f, 0.0f,
    0.8f, -0.8f, 0.0f,
    0.0f, 0.8f, 0.0f };
 
    // color data RGB
    float colorData[] = {
    1.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 1.0f };
 
 
    // 포지션과 색상을 저장하기 위한 버퍼를 생성한다.
    // Create the buffer objects
    GLuint vboHandles[2];
    // 버퍼 두개생성.
    glGenBuffers(2, vboHandles);
    GLuint positionBufferHandle = vboHandles[0];
    GLuint colorBufferHandle = vboHandles[1];
 
 
    // 각 버퍼의 데이타를 등록, 옮긴다.
    // Populate the position buffer
    // 포지션 버퍼를 바인드 한다.
    glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
    // 포지션 값을 등록한다.
    // 두번째 인자는 배열의 사이즈 이다. 세번째 인자는 해당 배열
    glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), positionData, GL_STATIC_DRAW);
 
    // Populate the color buffer
    // 생상 버퍼를 바인드한다.
    glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
    glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), colorData, GL_STATIC_DRAW);
 
 
    // 버퍼 오브젝트롤 설정하였기 때문에, 이것들을 vertex array obejct(VAO) 에 묶는다.
    // VAO 생성한다. (전역변수로 vaoHandle 필요)
    // Create and set-up the vertex array object
    glGenVertexArrays(1&vaoHandle);
    glBindVertexArray(vaoHandle);
 
    // 각 속성 인덱스의 generic vertex attribute 를 활성화 시킨다.
    // Enable the vertex attribute arrays
    glEnableVertexAttribArray(0); // for Vertex position
    glEnableVertexAttribArray(1); // for Vertex color
 
 
    // 버퍼 오브젝트와 generic vertex attribute index들을 연결시킨다.
    // Map index 0 to the position buffer
    glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
    // 첫번째인자 - generic attribute index, 두번째인자 - 각 vertex의 요소수(여기서는 3)(1,2,3 or 4)
    // 세번째인자 - 각 요소의 데이타 타입, 네번째인자 - normalize 여부, 다섯번째 인자 - byte offset
    // 여섯번째인자 - 버퍼의 시작 offset(여기서는 포지션값밖에 없기때문에 0)
    glVertexAttribPointer(03, GL_FLOAT, GL_FALSE, 0, (GLubyte*)NULL);
    // Map index 1 to the color buffer
    glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
    glVertexAttribPointer(13, GL_FLOAT, GL_FALSE, 0, (GLubyte*)NULL);
 
 
    // 타이머 스타트
    timer(0);
}
//---------------------------------------------------------------------
//
// transformModel
//
void transformObject(float scale, glm::vec3 rotationAxis, float rotationAngle, glm::vec3 translation) {
    glm::mat4 Model;
    Model = glm::mat4(1.0f);
    Model = glm::translate(Model, translation);
    Model = glm::rotate(Model, glm::radians(rotationAngle), rotationAxis);
    Model = glm::scale(Model, glm::vec3(scale));
    MVP = Projection * View * Model;
    glUniformMatrix4fv(mvpId, 1, GL_FALSE, &MVP[0][0]);
}
 
void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
 
    glBindVertexArray(vaoHandle);
 
    transformObject(1.0f, Z_AXIS, angle += 5.0f, glm::vec3(0.0f, 0.0f, 0.0f));
 
    // 3번째 인자 - 버택스의 수
    glDrawArrays(GL_TRIANGLES, 03);
 
 
 
    glutSwapBuffers(); // Now for a potentially smoother render.
}
 
void timer(int) {
    glutPostRedisplay();
    glutTimerFunc(1000 / FPS, timer, 0);
}
 
int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA);
 
    //윈도우 사이즈 변경
    glutInitWindowSize(512512);
 
    // top-left corner 초기 포지션으로 초기화
    glutInitWindowPosition(00);
 
    // 윈도우창 생성
    glutCreateWindow("Hello World");
 
 
    // glew를 초기화 해준다. opengl을 사용하기위해서
    GLenum err = glewInit();
    // glewInit()을 함으로써 모든 OpenGL라이브러리를 찾고 모든 사용가능한 함수포인터를 초기화한다.
 
    if (GLEW_OK != err)
    {
        fprintf(stderr, "Error initializing GLEW: %s\n",
            glewGetErrorString(err));
    }
 
    // to compile shader
    init();
 
    glutDisplayFunc(display);
 
 
    // glut의 이벤트 프로세싱 loop을 시작.
    glutMainLoop();
 
    return 0;
}
 
 
 
GLuint setShader(const char* shaderType, const char* shaderName)
{
    GLuint shaderObj;
    if (strcmp(shaderType, "vertex"== 0)
    {
        shaderObj = glCreateShader(GL_VERTEX_SHADER);
    }
    else if (strcmp(shaderType, "fragment"== 0)
    {
        shaderObj = glCreateShader(GL_FRAGMENT_SHADER);
    }
 
 
    if (0 == shaderObj)
    {
        fprintf(stderr, "Error creating shader obj.\n");
        exit(1);
    }
 
 
    // 2. 쉐이더 소스코드를 쉐이더 오브젝트로 복사한다.
    const GLchar* shaderCode = loadShaderAsString(shaderName);
    // 소스 배열에 여러 소스코드를 담을 수 있다.
    // 배열에 소스코드를 담은후.
    const GLchar* codeArray[] = { shaderCode };
    // vertShader object로 codeArray를 복사한다.
    // 첫번째 인자는 쉐이더 오브젝트, 두번째 인자는 소스코드의 총 개수 여기서는 shaderCode 한개만 들어가서 1
    // 세번째 인자는 코드를 넣은 배열, 네번째 인자는 각 소스코드의 길이를 넣은 int배열이다 여기서는 null character를 넣어서 자동으로 확인되기때무에 NULL을 넣었다.
    glShaderSource(shaderObj, 1, codeArray, NULL);
 
    // 3. 쉐이더를 컴파일 한다.
    glCompileShader(shaderObj);
 
 
    // 4. 컴파일 완료 확인.
    GLint result;
    glGetShaderiv(shaderObj, GL_COMPILE_STATUS, &result);
    if (GL_FALSE == result)
    {
        fprintf(stderr, "shader compilation failed!\n");
        GLint logLen;
        glGetShaderiv(shaderObj, GL_INFO_LOG_LENGTH, &logLen);
        if (logLen > 0)
        {
            char* log = (char*)malloc(logLen);
            GLsizei written;
            glGetShaderInfoLog(shaderObj, logLen, &written, log);
            fprintf(stderr, "Shader log:\n%s", log);
            free(log);
        }
    }
 
    return shaderObj;
}
 
char* loadShaderAsString(std::string fileName)
{
    // Initialize input stream.
    std::ifstream inFile(fileName.c_str(), std::ios::binary);
 
    // Determine shader file length and reserve space to read it in.
    inFile.seekg(0std::ios::end);
    int fileLength = inFile.tellg();
    char* fileContent = (char*)malloc((fileLength + 1* sizeof(char));
 
    // Read in shader file, set last character to NUL, close input stream.
    inFile.seekg(0std::ios::beg);
    inFile.read(fileContent, fileLength);
    fileContent[fileLength] = '\0';
    inFile.close();
 
    return fileContent;
}
cs

< 결과 >

 

<소스코드>

https://github.com/woonhak-kong/OpenGL_practice6_FPS

 

 

 

 

 

'OpenGL' 카테고리의 다른 글

Opengl mouse input  (0) 2021.10.01
Opengl Keyboard Input  (0) 2021.09.30
사각형과 삼각형 동시에 그리기  (0) 2021.09.23
uniform 변수를 이용하여 삼각형 rotate 하기.  (0) 2021.09.23
삼각형 그리기  (0) 2021.09.17

+ Recent posts