- uniform 변수를 이용하여 도형을 rotation 시킨다.

 

 

<basic.frag>

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

 

<basic.vert>

1
2
3
4
5
6
7
8
9
10
#version 400
layout(location = 0) in vec3 VertexPosition;
layout(location = 1) in vec3 VertexColor;
out vec3 Color;
uniform mat4 RotationMatrix;
void main()
{
    Color = VertexColor;
    gl_Position = RotationMatrix * vec4(VertexPosition, 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
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
#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>
 
 
GLuint vaoHandle;
GLuint programHandle;
GLuint setShader(const char* shaderType, const char* shaderName);
char* loadShaderAsString(std::string fileName);
 
 
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);
 
 
    /////////////////
    // VertexPosition 과 VertexColor변수를 의한 인덱스를 설정한다.
    // Bind index 0 to the shader input variable "VertexPosition"
    //glBindAttribLocation(programHandle, 0, "VertexPosition");
    // Bind index 1 to the shader input variable "VertexColor"
    //glBindAttribLocation(programHandle, 1, "VertexColor");
    ///////////////////
 
 
    // 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);
    }
 
    ////////////////////////////////////////////////////////////////////////
    // 활성화된 버텍스 인풋명과 인덱스번호를 보여준다.
    // Getting a list of active vertex input attributesand indices
    GLint maxLength, nAttribs;
    glGetProgramiv(programHandle, GL_ACTIVE_ATTRIBUTES,    &nAttribs);
    glGetProgramiv(programHandle, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,    &maxLength);
    GLchar* name = (GLchar*)malloc(maxLength);
 
    GLint written, size, location;
    GLenum type;
    printf(" Index | Name\n");
    printf("------------------------------------------------\n");
    for (int i = 0; i < nAttribs; i++) {
        glGetActiveAttrib(programHandle, i, maxLength, &written, &size&type, name);
        location = glGetAttribLocation(programHandle, name);
        printf(" %-5d | %s\n", location, name);
    }
    free(name);
    ////////////////////////////////////////////////////////////////////////
    // 활성화된 unifrom 변수를 보여준다.
    //Getting a list of active uniform variables
    GLint nUniforms, maxLen;
    glGetProgramiv(programHandle, GL_ACTIVE_UNIFORM_MAX_LENGTH,    &maxLen);
    glGetProgramiv(programHandle, GL_ACTIVE_UNIFORMS, &nUniforms);
    name = (GLchar*)malloc(maxLen);
 
    printf(" Location | Name\n");
    printf("------------------------------------------------\n");
    for (int i = 0; i < nUniforms; ++i) {
        glGetActiveUniform(programHandle, i, maxLen, &written,
            &size&type, name);
        location = glGetUniformLocation(programHandle, name);
        printf(" %-8d | %s\n", location, name);
    }
    free(name);
    ////////////////////////////////////////////////////////////////////////
 
 
    // 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);
 
 
}
 
void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
 
    // glm 라이브러리를 이용하여 rotate 매트릭스를 만든다.
    glm::mat4 rotationMatrix = glm::rotate(glm::mat4(1.0f), 30.f/* angle */,
                                           glm::vec3(0.0f, 0.0f, 1.0f));
 
 
    // 프로그램 오브젝트를 이용하여 uniform 변수의 location을 가져온다.
    // 만약 활성화된 uniform 변수가 아니라면 -1을 리턴한다.
    GLuint location = glGetUniformLocation(programHandle, "RotationMatrix");
 
    if (location >= 0)
    {
        // 메트릭스 값을 uniform 변수에 할당한다.
        // 첫번째인자 - location, 두번째 인자 - 매트릭스의 수 (uniform 변수는 배열이 될 수 있다.)
        // 세번째인자 - 매트릭스를 전달할때 transpose(뒤바뀜)되어야 하는지
        // 네번째인자 - 매트릭스의 포인터 uniform변수를 위한.
        glUniformMatrix4fv(location, 1, GL_FALSE, &rotationMatrix[0][0]);
    }
    glBindVertexArray(vaoHandle);
    // 3번째 인자 - 버택스의 수
    glDrawArrays(GL_TRIANGLES, 03); glDrawArrays(GL_TRIANGLES, 03);
 
 
    glFlush();
}
 
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_practice3_rotation/tree/master/OpenGL_Practice

'OpenGL' 카테고리의 다른 글

Opengl Keyboard Input  (0) 2021.09.30
FPS 적용하기  (0) 2021.09.30
사각형과 삼각형 동시에 그리기  (0) 2021.09.23
삼각형 그리기  (0) 2021.09.17
Glut으로 윈도우창 띄우기  (0) 2021.09.16

+ Recent posts