본문 바로가기
Game Development Tool 게임 제작툴

[2D 오픈소스 그래픽 라이브러리][libxd / piksel / p8g (Precessing) (추가)] 2D graphics library for C++ C++기반 2D 그래픽 라이브러리

by byungwoo733 2023. 2. 2.
728x90
반응형
SMALL

이번에 소개할 오픈소스 라이브러리는 아직 좀 더 알아보고 있는 한 개발자가 개발한 2개 2D 그래픽 라이브러리입니다. 

libxd는 C++기반 2D 그래픽 라이브러리며 그래픽 응용 프로그램을 만들 수 있는 직관적인 함수 모음을 제공하는 C++ 라이브러리입니다. 게임, 예술적 시각화 또는 고도로 정교한 물리 시뮬레이션을 할 수 있으며 libxd는 C++를 배우기 위한 도구로도 사용할 수 있습니다. OpenGL 기반이기 때문에 libxd는 하드웨어 가속 렌더링을 할 수 있다고 하는데 OpenGL 관련 API 호출되는 것은 아니라고 합니다. 지금 2D 그래픽 라이브러리에 초점을 잡고 있지만 장기적으로는 3D까지 구현도 곧 가능할 것으로 보입니다. libxd는 Linux, macOS 및 Windows를 지원합니다.

piksel libxd 라이브러리처럼 C++기반 2D 그래픽 라이브러리지만 차이점은 하드웨어 가속 렌더링 WebAssembly로 컴파일 가능 Processing과 유사한 직관적인 API라고 나와있습니다. 즉, C++로 구현한 것을 웹으로 컴파일이 가능하다는 특징이 있습니다. C++로 간단한 게임을 웹으로 구동하길 원한다면 WebAssembly로 통해서 할 수 있다는 말로 설명하면 되겠습니다. 

libxd /  piksel은  (libxd: LGPL-2.1 라이선스 / piksel: MIT 라이선스) 오스트리아 출신 개발자 Bernhard Fritz가 오픈소스로 개발한 2개의 C++기반 2D 그래픽 라이브러리입니다. 개발자의 말에 의하면 libxd는 Processing 및 p5.js 프로젝트에 영감을 받아서 개발했다고 하는데, 기본 예제 코드를 보면 Processing 와 p5.js 기본 코드 골격과 비슷하게 생겼습니다.

libxd 기본 코드 예제 - Hello rectangle!

#include <xd/xd.hpp>

using namespace xd;

void setup() {
    size(640, 480);
}

void draw() {
    rect(50, 50, 100, 100);
}

void destroy() {

}

 

piksel shape.cpp (with OpenGL GLM) 예제 코드

#include "shader.hpp"
#include <glm/gtc/type_ptr.hpp>
#include <fstream>
#include <sstream>

namespace piksel {

std::string readFile(const std::string& filename) {
    std::ifstream ifs(filename.c_str());
    std::stringstream ss;
    ss << ifs.rdbuf();
    return ss.str();
}

GLuint compile(GLenum shaderType, const std::string &shaderSource) {
    GLuint shader = glCreateShader(shaderType);
    const GLchar* c_str = shaderSource.c_str();
    glShaderSource(shader, 1, &c_str, NULL);
    glCompileShader(shader);

    GLint compileStatus;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
    if (compileStatus == GL_FALSE) {
        GLint infoLogLength;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);

        GLchar infoLog[infoLogLength];
        glGetShaderInfoLog(shader, infoLogLength, &infoLogLength, infoLog);
        
        glDeleteShader(shader);

        fprintf(stderr, "Shader compilation failed: %s\n", infoLog);

        return 0;
    }

    return shader;
}

GLuint link(GLuint vertexShader, GLuint fragmentShader) {
    GLuint program = glCreateProgram();
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);
    glLinkProgram(program);
    
    GLint linkStatus;
    glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
    if(linkStatus == GL_FALSE) {
        GLint infoLogLength = 0;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);

        GLchar infoLog[infoLogLength];
        glGetProgramInfoLog(program, infoLogLength, &infoLogLength, infoLog);

        glDeleteProgram(program);

        fprintf(stderr, "Program linking failed: %s\n", infoLog);

        return 0;
    }

    glDetachShader(program, vertexShader);
    glDetachShader(program, fragmentShader);

    return program;
}

void Shader::create(const std::string &vertexShaderSource, const std::string &fragmentShaderSource) {
    GLuint vertexShader;
    if ((vertexShader = compile(GL_VERTEX_SHADER, vertexShaderSource)) > 0) {
        GLuint fragmentShader;
        if ((fragmentShader = compile(GL_FRAGMENT_SHADER, fragmentShaderSource)) > 0) {
            program = link(vertexShader, fragmentShader);
        }
    }
}

void Shader::load(const std::string &vertexShaderFilename, const std::string &fragmentShaderFilename) {
    create(readFile(vertexShaderFilename), readFile(fragmentShaderFilename));
}

void Shader::createUniform(const std::string &uniformName) {
    uniforms[uniformName] = glGetUniformLocation(program, uniformName.c_str());
}

void Shader::setUniform(const std::string &uniformName, const int &i) {
    glUniform1iv(uniforms[uniformName], 1, &i);
}

void Shader::setUniform(const std::string &uniformName, const float &f) {
    glUniform1fv(uniforms[uniformName], 1, &f);
}

void Shader::setUniform(const std::string &uniformName, const glm::vec2 &v) {
    glUniform2fv(uniforms[uniformName], 1, glm::value_ptr(v));
}

void Shader::setUniform(const std::string &uniformName, const glm::vec3 &v) {
    glUniform3fv(uniforms[uniformName], 1, glm::value_ptr(v));
}

void Shader::setUniform(const std::string &uniformName, const glm::vec4 &v) {
    glUniform4fv(uniforms[uniformName], 1, glm::value_ptr(v));
}

void Shader::setUniform(const std::string &uniformName, const glm::mat4 &m) {
    glUniformMatrix4fv(uniforms[uniformName], 1, GL_FALSE, glm::value_ptr(m));
}

void Shader::use() {
    if (program) {
        glUseProgram(program);
    }
}

} // namespace nv

 

여전히 알아보고 있는 라이브러리로 다양한 테스트와 예제를 통해서 공부해보고 구현해봐야 알 수 있을 것 같습니다. 관심있는 분 공식 웹사이트에 방문해보시기 바랍니다. 관련 깃허브에서 다운로드할 수 있습니다.

최근에는 C / C++, Java, JavaScript, TypeScript언어도 지원하는 2D 그래픽 라이브러리 "p8g"라는 언어도 공개 했으니 검색해보시기 바랍니다. (웹에디터도 있음)

p8g (Precessing) 기본 코드

import p8g, {
  background,
  createCanvas,
  rect,
} from 'https://unpkg.com/p8g.js';

p8g.draw = () => {
  background(220);
  rect(50, 50, 100, 100);
};

createCanvas(320, 320);

*Bernhard Fritz의 itch.io페이지에는 piksel 라이브러리로 만든 Mario breaks out  게임 (piksel 공식 페이지 예제에도 있고 깃허브 페이지에도 itch.io페이지 링크 있음)이 있습니다.

====================================

구글 검색창에 "libxd 라이브러리 & piksel 라이브러리" 검색

 

728x90
LIST

댓글