본문 바로가기
공허의 유산/표현의 자유

[opengl].[#2.GLSL] 01. OpenGL 1.1 기반의 랜더링

by 바른생활머시마 2020. 8. 9.
728x90
반응형

최신의 OpenGL과 Shader를 사용하기 위해 glew 연동까지 준비가 되었습니다.

 

 

1. 기본 랜더링 코드

이후에 진행 될 GLSL 기반의 랜더링과 비교를 용이하게 하기 위해, 1.1 기반의 랜더링에 조금 신경을 써보겠습니다.

삼각형 대신 glut에서 제공되는 주전자 그리기 기능으로 주전자를 그리고, 배경색이나 Depth 버퍼 초기화도 추가했습니다.

void display() {

    //Clear
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    //Draw
    glColor3f(0.0f, 0.0f, 1.0f);
	glutSolidTeapot(0.5);
	glFinish();
}

 

2. 조명 효과

조명 효과를 위해서, 최소한의 파라미터로 조명을 활성화 시키겠습니다. glew는 활성화 시키지 않겠습니다.

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutCreateWindow("OpenGL");

	//initGLEW();
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);

    glutDisplayFunc(display);
    glutMainLoop();
    return 0;
}

 이 상태로 랜더링을 해 보면 아래와 같이 주전자가 흰색으로 반쯤 보이네요.(사용자 환경에 따라 다르게 나올 수도 있을 것 같습니다.)

 OpenGL의 조명에 대해서도 꽤 많은 양의 학습이 필요한데, 여기서 다룰 수 없으니, 아주 초간단 요약만 좀 하겠습니다.

 검색을 조금 해 보니, 요즘은 opengl 조명이라고 하면 쉐이더로 조명 설정하는 내용이 많고, 1.1 조명 설정에 대한 내용은 찾아보기 어렵네요. 억지로 1.1을 넣어서 검색하면 나오긴 합니다.

http://math.hws.edu/graphicsbook/c4/s2.html

 

Introduction to Computer Graphics, Section 4.2 -- Light and Material in OpenGL 1.1

Section 4.2 Light and Material in OpenGL 1.1 In this section, we will see how to use light and material in OpenGL. The use of light and material must be enabled by calling glEnable(GL_LIGHTING). When lighting is disabled, the color of a vertex is simply th

math.hws.edu

 

 조명을 쓰려면 glEnable(GL_LIGHTING)으로 조명 기능을 활성화 시켜줘야 하고,

 OpenGL에서 지원하는 기본 조명은 8개가 있는데 각 조명도 별도로 활성화(glEnable(GL_LIGHTn)) 시켜줘야 합니다.

 조명에는 아주 다양한 속성이 있는데, 색상/위치/방향/반사특성 등을 정할 수 있습니다. 또, 조명을 사용하게 되면, 재질도 정해줘야 하는데, 재질 X 조명의 결과가 화면에 그려지게 됩니다. 그래서, 조명 설정을 하지 않은 상태에서는 파란색 삼각형이 그려진 것이고, 조명을 설정하니, 재질 정보가 없으니 기본값인 흰색이 적용되었습니다. 이 설정 색상(glColor)이 재질로 사용되게 하는 옵션이 있는데, glEnable(GL_COLOR_MATERIAL)을 적용하면, 삼각형을 봤을 때 처럼 지정 된 색상이 (재질의 diffuse 성분으로 적용되어) 나타납니다.

 입체감을 나타내기 위해서는, 조명 외에도 Depth test, Font face, Projection volume 등 다양한 설정이 필요한데, 그건 여기서 따로 설명하지 않고, 아래 코드로 기본적인 입체감이 확인되는 설정을 한 것으로 하겠습니다.

 

void initGL()
{
	//Enable/Disable
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_DEPTH_TEST);

	//Rendering
	glFrontFace(GL_CCW);

	//Light
	GLfloat lightPos[] = { 0.f, 0.f, 10.f, 0.f };
	glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
	glEnable(GL_COLOR_MATERIAL);

	//Modelview and projection
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-1.f, 1.f, -1.f, 1.f, -1.f, 1.f);
	glMatrixMode(GL_MODELVIEW);
}

아래와 같이 나옵니다.

 

뒤에서 살펴보겠지만, Shader로 이러한 조명 효과를 내기 위해서는 꽤 많은 작업이 필요합니다. 이 작업은 조명을 위한 작업이라기 보다는, Shader를 쓰기 위한 작업입니다. 이렇게 뭐 하나 새로운 것 하려면 쉽지 않죠. 그렇지만, 어렵게 해 둔 후, 그 다음 그 기반으로 뭔가 만들어 가는 것은 많은 작업을 필요로 하지 않습니다. OpenGL 초기 환경 설정은 번거루웠지만, 그 상태에서 조명 적용은 간단히 된 것 처럼 말이죠.

 

 

 

3. animation 적용

 Shader의 참맛은 표면 형상에 따른 변화가 부드럽게 이어지는 것을 보는데 있어요. 그래서, 굴곡을 느낄 수 있도록 회전 animation도 걸어두겠습니다. 조명의 느낌이 잘 나도록 색상도 조금 밝게 수정했습니다.

 glut의 창을 만들고, 랜더링 하는 설정을 조금 손보고, 간단한 회전 코드를 추가하겠습니다.

이 상태에서는, glew를 초기화 해도 아무 것도 달라지지 않습니다.

이렇게 1.1로 랜더링 된 상태에서, 이 상태를 GLSL을 이용해서 만드는 과정을 쉐이더로 직접 구현 해 보면, OpenGL pipeline을 이해하는데 큰 도움이 되고, 그래서, GLSL이 무엇을 할 수 있는지 가늠하는데 도움이 됩니다.

 

 

반응형

 

여기까지 구현한 코드는 아래와 같습니다.

#include <iostream>

#include <gl/glew.h>
#include <GL/glut.h>


float rotate_angle = 0.f;
void changeSize(int w, int h) {
	if (h == 0)	h = 1;
	float ratio = 1.0 * w / h;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glViewport(0, 0, w, h);
	glOrtho(-1.f, 1.f, -1.f, 1.f, -1.f, 1.f);
	glMatrixMode(GL_MODELVIEW);
}

void display() {

    //Clear
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    //Draw
	glPushMatrix();
	glRotatef(rotate_angle, 0.f, 1.f, 0.f);
	glutSolidTeapot(0.5);
	glPopMatrix();
	glFlush();
	glutSwapBuffers();
	rotate_angle = rotate_angle + 0.1f;
	if (rotate_angle > 360.f) rotate_angle -= 360.f;
}

void initGLEW()
{
	//Initialize GLEW
	GLenum err = glewInit();
	if (GLEW_OK != err)
	{
		fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
		exit(0);
	}
	fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));

	//Check Shader
	//ARB
	if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
		printf("Ready for GLSL (ARB)\n");
	else
	{
		printf("No GLSL support\n");
		exit(0);
	}

	//OpenGL 4.6
	if (glewIsSupported("GL_VERSION_4_6"))
		printf("Ready for OpenGL 4.6\n");
	else {
		printf("OpenGL 4.6 not supported\n");
		exit(0);
	}
}

void initGL()
{
	//Enable/Disable
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_DEPTH_TEST);

	//Rendering
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glFrontFace(GL_CCW);
	glColor3f(0.0f, 0.5f, 1.0f);

	//Light
	GLfloat lightPos[] = { 0.f, 0.f, 10.f, 0.f };
	glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
	glEnable(GL_COLOR_MATERIAL);

	//Modelview and projection
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-1.f, 1.f, -1.f, 1.f, -1.f, 1.f);
	glMatrixMode(GL_MODELVIEW);
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(300, 300);
	glutCreateWindow("OpenGL");
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
	glutDisplayFunc(display);
	glutReshapeFunc(changeSize);
	glutIdleFunc(display);

	initGLEW();
	initGL();

    glutMainLoop();
    return 0;
}

 

 

다음 시간부터, 본격적으로 쉐이더 쓸 준비를 해볼께요.

https://learn-and-give.tistory.com/13

 

[opengl].[#2.GLSL] 02. Shader 사용 기반 코드 작성

Shader를 사용하기 위한 준비를 해 보겠습니다. 참고가 될 만한 Reference를 잠시 찾아봤는데, 옛 생각이 나서 예전에 많이 보던 사이트에 한번 가봤습니다. NeHe gamedev https://nehe.gamedev.net/ NeHe Productions

learn-and-give.tistory.com

 

728x90
반응형

댓글