실행 화면

 

소스코드

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
#include <fstream>
#include <string>

GLuint VBO, VAO, shader;

std::string ReadFile(const char* filePath)
{
	std::string content;
	std::ifstream fileStream(filePath, std::ios::in);

	while (!fileStream.is_open())
	{
		printf("Failed to read %s file! The file doesn't exist.\n", filePath);
		return "";
	}

	std::string line = "";
	while (!fileStream.eof())
	{
		std::getline(fileStream, line);
		content.append(line + "\n");
	}

	fileStream.close();
	return content;
}

GLuint AddShader(const char* shaderCode, GLenum shaderType)
{
	GLuint new_shader = glCreateShader(shaderType);

	const GLchar* code[1];
	code[0] = shaderCode;

	glShaderSource(new_shader, 1, code, NULL);

	GLint result = 0;
	GLchar err_log[1024] = { 0 };

	glCompileShader(new_shader);
	glGetShaderiv(new_shader, GL_COMPILE_STATUS, &result);
	if (!result)
	{
		glGetShaderInfoLog(new_shader, sizeof(err_log), NULL, err_log);
		printf("Error compiling the %d shader: '%s'\n", shaderType, err_log);
		return 0;
	}
	return new_shader;
}

void CompileShader(const char* vsCode, const char* fsCode)
{
	GLuint vs, fs;

	shader = glCreateProgram();

	if (!shader)
	{
		printf("Error: Cannot create shader program.");
		return;
	}

	vs = AddShader(vsCode, GL_VERTEX_SHADER);
	fs = AddShader(fsCode, GL_FRAGMENT_SHADER);
	glAttachShader(shader, vs);  // Attach shaders to the program for linking process.
	glAttachShader(shader, fs);

	GLint result = 0;
	GLchar err_log[1024] = { 0 };

	glLinkProgram(shader);  // Create executables from shader codes to run on corresponding processors.
	glGetProgramiv(shader, GL_LINK_STATUS, &result);
	if (!result)
	{
		glGetProgramInfoLog(shader, sizeof(err_log), NULL, err_log);
		printf("Error linking program: '%s'\n", err_log);
		return;
	}
}

void CreateShaderProgramFromFiles(const char* vsPath, const char* fsPath)
{
	std::string vsFile = ReadFile(vsPath);
	std::string fsFile = ReadFile(fsPath);
	const char* vsCode = vsFile.c_str();
	const char* fsCode = fsFile.c_str();

	CompileShader(vsCode, fsCode);
}

void CreateTriangle()
{
	GLfloat vertices[] = {
		-1.0f, -1.0f, 0.0f,
		1.0f, -1.0f, 0.0f,
		0.0f, 1.0f, 0.0f
	};

	glGenVertexArrays(1, &VAO);
	glBindVertexArray(VAO);

	glGenBuffers(1, &VBO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);

	glBindBuffer(GL_ARRAY_BUFFER, 0);

	glBindVertexArray(0);
}

int main(void)
{
	if (!glfwInit())
		exit(EXIT_FAILURE);

	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

	GLFWwindow* window = glfwCreateWindow(1080, 720, "title", NULL, NULL);
	if (!window)
	{
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	glfwMakeContextCurrent(window);

	int framebuf_width, framebuf_height;
	glfwGetFramebufferSize(window, &framebuf_width, &framebuf_height);
	glViewport(0, 0, framebuf_width, framebuf_height);

	if (glewInit() != GLEW_OK)
	{
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	CreateTriangle();
	CreateShaderProgramFromFiles("Shaders/shader.vert", "Shaders/shader.frag");

	while (!glfwWindowShouldClose(window))
	{
		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		glUseProgram(shader);

		glBindVertexArray(VAO);
		glDrawArrays(GL_TRIANGLES, 0, 3);
		glBindVertexArray(0);

		glUseProgram(0);

		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	glfwTerminate();

	return 0;
}

 

Vertex shader

#version 460

layout (location = 0) in vec3 pos;

void main()
{
	gl_Position = vec4(pos, 1.0);
}

#version GLSL버전

0번째 vetex attribute를 가져와 vec3 pos 변수에 넣음

gl_position은 미리 정의된 vertex shader의 출력값으로 clip-space에서의 vertex 좌표

 

Fragment shader

#version 460

out vec4 color;

void main()
{
    color = vec4(0.0, 1.0, 0.0, 1.0);
}

#version GLSL버전

출력 변수로 vec4 color 선언, 내장 변수가 아니므로 변수명은 마음대로

 

관습적으로 vetex shader의 파일명은 xxxx.vert로 fragment shader의 파일명은 xxxx.frag로 함

실행 화면

 

소스코드

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdlib.h>

int main(void)
{
	if (!glfwInit())
		exit(EXIT_FAILURE);

	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

	GLFWwindow* window = glfwCreateWindow(1080, 720, "title", NULL, NULL);
	if (!window)
	{
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	glfwMakeContextCurrent(window);

	int framebuf_width, framebuf_height;
	glfwGetFramebufferSize(window, &framebuf_width, &framebuf_height);
	glViewport(0, 0, framebuf_width, framebuf_height);

	if (glewInit() != GLEW_OK)
	{
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	// NDC space (-1.0 ~ 1.0)
	float vertices[] = {
	-0.5f, -0.5f, 0.0f,
	 0.5f, -0.5f, 0.0f,
	 0.0f,  0.5f, 0.0f
	};

	GLuint VAO;  // 아래 모든 작업을 하나의 state로 저장할 OpenGL Object ID (vertex array)
	GLuint VBO; // vertex buffer object ID (vertex buffer)

	glGenVertexArrays(1, &VAO); // VAO 생성
	glBindVertexArray(VAO); // VAO를 OpenGL context에 연결(bind)

	glGenBuffers(1, &VBO);  // pram:(만들고자 하는 버퍼의 갯수, 버퍼의 ID 포인터)
	glBindBuffer(GL_ARRAY_BUFFER, VBO);  // param:(target, 버퍼의 ID)
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // parm:(target, 복사할 데이터 크기, 복사할 데이터, 힌트)

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GL_FLOAT), (void*)0); // location pointer parm:(0, 3차원, float, no normalize, stride, start offset)
	glEnableVertexAttribArray(0);

	//glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), (void*)(3 * sizeof(GL_FLOAT))); // uv pointer example
	//glEnableVertexAttribArray(1);

	glBindBuffer(GL_ARRAY_BUFFER, 0); // ID 대신 0을 넣으면 unbind
	glBindVertexArray(0);


	while (!glfwWindowShouldClose(window))
	{
		glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);
		glBindVertexArray(VAO);
		glDrawArrays(GL_TRIANGLES, 0, 3);
		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	glfwTerminate();

	return 0;
}

 

함수 정리

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4)

기계에서 호환하는 OpenGL major 버전 설정 

ex) Version 4.5 - Major 4

 

glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5)

기계에서 호환하는 OpenGL minor 버전 설정 

ex) Version 4.5 - Minor 5

 

glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)

OpenGL Profile 설정

GLFW_OPENGL_CORE_PROFILE / GLFW_OPENGL_COMPAT_PROFILE / GLFW_OPENGL_ANY_PROFILE 가 올 수 있음

OpenGL 버전이 3.2 이하면 반드시 GLFW_OPENGL_ANY_PROFILE을 사용해야 함.

 

glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE)

현재 OpenGL 버전에서 deprecated된 함수들을 삭제할지 여부

GL_TRUE / GL_FALSE 가 올 수 있음

 

glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer)

https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttribPointer.xhtml

 

glVertexAttribPointer - OpenGL 4 Reference Pages

 

www.khronos.org

 

 

다른 함수들은 아래 레퍼런스나 구글에 쳐보면 잘 나온다.

https://www.glfw.org/docs/3.3/window_guide.html#GLFW_OPENGL_PROFILE_hint

 

GLFW: Window guide

This guide introduces the window related functions of GLFW. For details on a specific function in this category, see the Window reference. There are also guides for the other areas of GLFW. Window objects The GLFWwindow object encapsulates both a window an

www.glfw.org

 

실행 화면

 

소스코드

#include <GLFW/glfw3.h>

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);

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT);

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}

 

우선 OpenGL 개발을 위한 유명한 오픈소스 라이브러리인 GLFW와 GLES를 연동한다.

 

1. GLFW 설치

https://www.glfw.org/download.html

 

Download

GLFW source code and binary distribution download links.

www.glfw.org

위 사이트에서 원하는 버전의 Windows pre-compiled binaries를 다운로드한다.

나는 Visual studio에서 x86으로 컴파일을 할 것이기 때문에 32-bit Windows binaries를 다운로드했다.

 

2. GLES 설치

http://glew.sourceforge.net/

 

GLEW: The OpenGL Extension Wrangler Library

The OpenGL Extension Wrangler Library The OpenGL Extension Wrangler Library (GLEW) is a cross-platform open-source C/C++ extension loading library. GLEW provides efficient run-time mechanisms for determining which OpenGL extensions are supported on the tar

glew.sourceforge.net

위 사이트에서 Windows 32-bit and 64-bit binary를 다운로드한다.

 

3. Visual Studio 세팅

정적 라이브러리를 프로젝트에서 사용할 수 있게 연동해준다.

  • <프로젝트 세팅 → C/C++ → 일반 → 추가포함 디렉터리>에 include(헤더파일) 경로를 추가해준다.

 

  • <프로젝트 세팅 → 링커 → 일반 → 추가 라이브러리 디렉터리>에 lib파일 경로를 추가해준다.

 

 

  • <프로젝트 세팅 → 링커 → 입력 → 추가 종속성>에 사용할 lib파일 이름을 추가해준다.

 

참고한 블로그

https://gongdolhoon.tistory.com/entry/1-OpenGL-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0

 

[C++/Modern OpenGL] 1. OpenGL 개발 환경 세팅하기

2. OpenGL 개발 환경 세팅하기  "시작이 반이다. (Well begun is half done.)" - Aristotle  라이브러리를 사용한 경험이 잦은 사람들은 어떤 라이브러리를 가져올 때, 세팅하는 것이 어렵지는 않을 것입니다.

gongdolhoon.tistory.com

 

Unity Editor에서 플레이 중 위와 같은 오류가 뜨면서 Unity가 종료되는 에러가 발생했다.

이 문제로 이틀을 고생했다.

해결방법을 찾아보았다.

 

1. 클린 부팅

https://answers.microsoft.com/ko-kr/windows/forum/all/microsoft-visual-c-runtime-library/b721da15-059d-477b-98eb-6bfacf575191

 

Microsoft Visual C++ Runtime Library 런타임 에러 문의

Microsoft Visual C++ Runtime Library 런타임 에러가 뜨는데 Program: C\Program Files... 라고만 나오니 어디가 문제인지 모르겠고... 같은 문제 겪으셨거나 해결하신 분 방법 아시면 알려주세요... (윈도우10 x64)

answers.microsoft.com

Microsoft에서 공식 답변해준 방법인데 나는 효과가 없었다.

아마도 이건 개발자가 아닌 일반 사용자들이 어떤 프로그램을 사용했을 떄 위와 같은 에러가 발생하면 쓰는 방법인 듯 하다.

 

 

2. Windows 구성 요소 저장소에서 파일 손상 검사

https://barista7.tistory.com/555

 

Microsoft Visual C++ Runtime Library 런타임 에러

Microsoft Visual C++ Runtime Library 런타임 에러가 뜨는데 Program : C\Program... 라고만 나오니 어디가 문제인지 전혀 모르겠다. 분명히 이와 같은 문제 겪었던 사람들이 있을것이란 생각에 검색을 해보았

barista7.tistory.com

위 블로그에 자세히 나와있다.

똑같이 효과는 없었던 걸루,,,

 

 

3. Visual C++ Redistributable Library 재설치

제어판에서 Visual C++ Redistributable 파일들을 모두 삭제하고 최신 버전으로 재설치한다.

설치는 아래 링크에서.

https://support.microsoft.com/ko-kr/topic/%EC%A7%80%EC%9B%90%EB%90%98%EB%8A%94-%EC%B5%9C%EC%8B%A0-visual-c-%EB%8B%A4%EC%9A%B4%EB%A1%9C%EB%93%9C-2647da03-1eea-4433-9aff-95f26a218cc0

 

지원되는 최신 Visual C++ 다운로드

시간을 최대한 활용하기 위한 구독

support.microsoft.com

 

블로그를 여러개 찾아봤는데 위 3가지 방법으로 대부분 해결되는 것 같다.

사실 나는 알고보니 호출중인 DLL에서 발생한 오류였음ㅜㅜ

https://modoocode.com/332

 

씹어먹는 C++ - <19 - 2. C++ 프로젝트를 위한 CMake 사용법>

 

modoocode.com

 

 

스마일게이트 온라인 게임잼에 참여했습니다.

게임잼을 무척 좋아하기 떄문에.. 기대반 설렘반..

이전에 참여했던 게임잼은 오프라인이거나 온라인으로 진행하면 Discord를 사용했는데 스마게 게임잼은 Gather를 시용했습니다.

그런데 참여자가 100명 가까이 되다 보니 모여 있으면 렉이 걸리고 네트워크가 불안정하면 많이 튕기더군요,,ㅜㅜ

그런 점에서 Gather는 귀엽고 presence가 높긴 하지만 Discord가 음질이나 편리성 부분에선 더 좋지 않나 생각했습니다.

팀 꾸리고 난 뒤에는 바로 팀원들끼리는 Discord 서버파서 사용했어요!

 

이번 게임잼의 주제는 "바다로 휴가를 떠난 당신.. 그러나?" 였습니다.

 

다양한 재밌는 기획 아이디어들이 나왔습니다. 바다에 가서 즉석으로 카페를 차리는 타이쿤 게임도 기억에 남네요ㅋㅋㅋ

2박 3일동안 다같이 달렸습니다~

The Sirens

저희 팀은 퍼즐 어드벤처 공포 게임을 만들었습니다.

 

<게임 간단 소개>

슬픔을 잊기 위해 바다로 떠난 주인공, 갑자기 배가 침몰되었다.

무사히 살아남아 눈을 떠보니 이상한 방 안에 갇혀있었다. 

누가 납치한건지, 이유는 무엇인지 밝혀가는 퍼즐 어드벤쳐 게임 입니다.

 

 

<팀원>

기획자: 송채현, 이종현, 오민서, 박건우

아트: 이지영, 오민서

프로그래머: 강영묵, 정보라 

 

 

<플레이 영상>

https://youtu.be/E4ch1uGUL_w

 

 

<후기>

게임잼은 역시 재밌다.

막판에는 체력적으로 힘들기도 했지만 팀원들 모두 열심히 해준 덕에 재밌게 참여할 수 있었습니다.

뭔가 살면서 다양한 사람들을 만날 기회가 그리 많지 않은데 특히 요즘 같은 코로나 시국에는 더욱,,

이렇게 게임이라는 공통된 관심사를 가진 무작위의 사람들이 만나서 의견을 나누고 이야기를 하고 협업을 한다는 것 자체가 참 좋은 경험인 것 같아요.

이런 행사가 아니라면 평생 만나보지 못할 사람들일 수도 있잖아요? 

아무튼,, 시간과 체력이 된다면 저는 게임잼에 계속 참여하고 싶단 생각이 들었어요.

더 다양한 게임을 만들어보고 싶단 생각!!

후기 끄읕

 

 

 

아래는 STOVE 커뮤니티에 올라간 게임잼 후기입니다.

https://page.onstove.com/indie/global/view/7405154

 

연어회_The Sirens_210725_게임 잼 후기

<팀명>연어회: 맛있는 생각이 떠올라서<구성원>기획자: 송채현, 이종현, 오민서, 박건우아트: 이지영, 오민서프로그래머: 강영묵, 정보라 <게임 사진><게임 간단 소개>슬픔을 잊기 위해 바다로 떠

page.onstove.com

 

대학교 2학년 때 처음으로 도전해본 3D 게임인데,,, 지금보니 몬스터가 슬라이딩 하면서 걷는다,,, ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

 

게임 이름: Zombie City

게임 장르: FPS

개발 엔진: Unity

 

https://www.youtube.com/watch?v=Ntk_Gwji02A 

 

대학교 1학년 때 처음으로 혼자 완성해본 작고 소중한 게임..ㅎㅎ

 

게임 이름: Into The Space

게임 장르: 2D Shooting

개발 엔진: Unity

 

영상에서 보스 스테이지를 보여드리기 위해 보스가 출현하는 점수를 임의로 낮쳐 놓은 상태입니다.

 

https://youtu.be/fvVrlK98FPY

 

대학교 입학하고 1학년 때 처음으로 만들어본 작고 소중한 게임,,ㅎㅎ

 

게임 이름 : Euro

게임 장르 : 2D Roguelike

개발 엔진 : Unity

팀 : 보보봉(4명)

 

https://youtu.be/55g67o8ogKE

 

 

+ Recent posts