tried to implement rendering with bgfx, dnf

This commit is contained in:
Aaro Koivukangas
2025-05-19 08:34:42 +03:00
parent c4a8ab7cb8
commit d6bf49d19e
21 changed files with 641 additions and 92 deletions
+2
View File
@@ -1,6 +1,8 @@
thirdparty thirdparty
build
temp temp
.cache
main main
*.o *.o
+98
View File
@@ -0,0 +1,98 @@
cmake_minimum_required(VERSION 4.0)
project(galaxy-engine C CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 99)
# creates compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Googletest (aka gtest)
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
)
FetchContent_MakeAvailable(googletest)
FetchContent_Declare(
bgfx
URL https://github.com/bkaradzic/bgfx.cmake/releases/download/v1.129.8866-492/bgfx.cmake.v1.129.8866-492.zip
)
FetchContent_Declare(
glfw
URL https://github.com/glfw/glfw/releases/download/3.4/glfw-3.4.zip
)
FetchContent_MakeAvailable(glfw bgfx)
set(SOURCES
src/galaxy.cpp
src/gwindow.cpp
src/grenderer.cpp
src/logger.cpp
src/gshader.cpp
src/vertex.cpp
src/todo.cpp
)
# Includes bgfx/src for #include <bgfx_shader.sh> inside shaders
set(BGFX_SHADER_INCLUDE_PATH "${BGFX_DIR}/src" CACHE STRING "bgfx include path")
set(GALAXY_SHADER_BIN_DIR "${CMAKE_BINARY_DIR}/generated/shaders" CACHE STRING "Shader install location")
set(SHADER_SOURCES
src/shaders/v_simple.sc
src/shaders/f_simple.sc
)
bgfx_compile_shaders(
TYPE VERTEX
SHADERS src/shaders/v_simple.sc
VARYING_DEF ${CMAKE_SOURCE_DIR}/src/shaders/varying.def.sc
OUTPUT_DIR ${CMAKE_BINARY_DIR}/generated/shaders
)
bgfx_compile_shaders(
TYPE FRAGMENT
SHADERS src/shaders/f_simple.sc
VARYING_DEF ${CMAKE_SOURCE_DIR}/src/shaders/varying.def.sc
OUTPUT_DIR ${CMAKE_BINARY_DIR}/generated/shaders
)
configure_file(include/env-vars.h.in ${CMAKE_BINARY_DIR}/generated/include/env-vars.h)
set(INCLUDE_DIRS
${BGFX_DIR}/include
${BX_DIR}/include
${CMAKE_BINARY_DIR}/generated/include # env-vars.h
)
add_library(galaxy-engine-lib ${SOURCES} ${SHADER_SOURCES})
add_executable(galaxy-engine src/main.cpp)
target_include_directories(galaxy-engine PRIVATE include ${INCLUDE_DIRS})
target_include_directories(galaxy-engine-lib PRIVATE include ${INCLUDE_DIRS})
target_link_libraries(galaxy-engine galaxy-engine-lib bgfx glfw)
# Testing
enable_testing()
set(TESTING_SOURCES
test/todo.cpp
${SOURCES}
)
add_executable(tests ${TESTING_SOURCES})
target_link_libraries(
tests
GTest::gtest_main
bgfx
glfw
)
target_include_directories(tests PRIVATE include ${INCLUDE_DIRS})
include(GoogleTest)
gtest_discover_tests(tests)
+3
View File
@@ -0,0 +1,3 @@
#pragma once
#define GALAXY_SHADER_BIN_DIR "@GALAXY_SHADER_BIN_DIR@"
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include "gshader.h"
#include "grenderer.h"
#include "gwindow.h"
#include "logger.h"
class Galaxy {
public:
Galaxy();
~Galaxy();
Galaxy(GWindow *w, GRenderer *r, Logger *l)
: window(w), renderer(r), logger(l) {};
void init();
void run();
private:
Logger *logger;
GWindow *window;
GRenderer *renderer;
};
static void glfw_errorCallback(int error, const char *description);
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <vector>
#include "gwindow.h"
#include "logger.h"
#include "vertex.h"
class GRenderer {
public:
GRenderer(GWindow *w, Logger *l);
~GRenderer();
void init();
void update();
private:
Logger *logger;
GWindow *window;
bgfx::ShaderHandle vsh;
bgfx::ShaderHandle fsh;
bgfx::ProgramHandle program;
bgfx::VertexBufferHandle vbh;
bgfx::IndexBufferHandle ibh;
std::vector<PosColVertex> *vertexes;
std::vector<int> *tri_list;
bgfx::VertexLayout layout;
void bgfx_init();
void shader_init();
bgfx::ShaderHandle load_shader(const char *name);
};
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include "bgfx/bgfx.h"
#include "logger.h"
class GShader {
public:
GShader(Logger *l) : logger(l) {};
~GShader() {};
void init();
bgfx::ShaderHandle loadShader(const char *name);
private:
Logger *logger;
};
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include "GLFW/glfw3.h"
#include "logger.h"
class GWindow {
public:
GWindow(int w, int h, Logger *l) : width(w), height(h), logger(l) {};
~GWindow();
void init();
void processInput();
GLFWwindow *getWindow() { return window; };
int getWidth() const { return width; }
int getHeight() const { return height; }
private:
int width;
int height;
Logger *logger;
GLFWwindow *window;
};
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include <iostream>
#include <string>
// TODO add log levels => for ex. display only info and errors
#define LOG_INFO(x) this->logger->info(x);
#define LOG_DEBUG(x) this->logger->debug(x);
#define LOG_ERROR(x) this->logger->error(x);
#define LOG_WARN(x) this->logger->warn(x);
class Logger {
public:
Logger();
Logger(std::ostream *l);
Logger(const Logger &old_logger);
void info(const std::string msg);
void debug(const std::string msg);
void error(const std::string msg);
void warn(const std::string msg);
private:
std::ostream *outputDest;
};
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include "bgfx/bgfx.h"
#include <cstdint>
class PosColVertex {
public:
PosColVertex(float x, float y, float z, uint32_t abgr)
: x(x), y(y), z(z), abgr(abgr) {
this->init();
};
~PosColVertex() {};
void init();
bgfx::VertexLayout getLayout() { return this->layout; };
private:
float x;
float y;
float z;
uint32_t abgr;
bgfx::VertexLayout layout;
};
+46
View File
@@ -0,0 +1,46 @@
#include "logger.h"
#include "galaxy.h"
const int W_WIDTH = 800;
const int W_HEIGHT = 600;
Galaxy::Galaxy() {
Logger *logger = new Logger(&std::cout);
this->logger = logger;
LOG_INFO("Starting the engine...");
GWindow *window = new GWindow(W_WIDTH, W_HEIGHT, logger);
GRenderer *renderer = new GRenderer(window, logger);
this->window = window;
this->renderer = renderer;
LOG_DEBUG("Done creating new things.");
}
Galaxy::~Galaxy() {
LOG_INFO("Shutting down the engine...");
delete this->renderer;
delete this->window;
delete this->logger;
}
void Galaxy::init() {
LOG_DEBUG("Initializing the engine...");
this->window->init();
this->renderer->init();
}
void Galaxy::run() {
LOG_DEBUG("Running the main loop...");
unsigned int counter = 0;
while (!glfwWindowShouldClose(this->window->getWindow())) {
this->window->processInput();
this->renderer->update();
glfwPollEvents();
counter++;
}
}
+227
View File
@@ -0,0 +1,227 @@
#define BX_CONFIG_DEBUG 0
#include "bgfx/bgfx.h"
#include "bgfx/platform.h"
#include "bx/math.h"
#include <fstream>
#include <stdexcept>
#include <vector>
#include <cstring>
#include "GLFW/glfw3.h"
#define GLFW_EXPOSE_NATIVE_X11
#include "GLFW/glfw3native.h"
#include "env-vars.h"
#include "grenderer.h"
#include "logger.h"
static PosColVertex st_vertexes[] =
{
{-1.0f, 1.0f, 1.0f, 0xff000000 },
{ 1.0f, 1.0f, 1.0f, 0xff0000ff },
{-1.0f, -1.0f, 1.0f, 0xff00ff00 },
{ 1.0f, -1.0f, 1.0f, 0xff00ffff },
{-1.0f, 1.0f, -1.0f, 0xffff0000 },
{ 1.0f, 1.0f, -1.0f, 0xffff00ff },
{-1.0f, -1.0f, -1.0f, 0xffffff00 },
{ 1.0f, -1.0f, -1.0f, 0xffffffff },
};
static const uint16_t st_tri_list[] =
{
0, 1, 2,
1, 3, 2,
4, 6, 5,
5, 6, 7,
0, 2, 4,
4, 2, 6,
1, 5, 3,
5, 7, 3,
0, 4, 1,
4, 5, 1,
2, 3, 6,
6, 3, 7,
};
GRenderer::GRenderer(GWindow *w, Logger *l) : window(w), logger(l) {
// TODO this is obviously static data
static std::vector<PosColVertex> vertexes = {{0.5f, 0.5f, 0.0f, 0xff0000ff},
{0.5f, -0.5f, 0.0f, 0xff0000ff},
{-0.5f, -0.5f, 0.0f, 0xff00ff00},
{-0.5f, 0.5f, 0.0f, 0xff00ff00}};
static std::vector<int> tri_list = {0, 1, 3, 1, 2, 3};
this->vertexes = &vertexes;
this->tri_list = &tri_list;
}
GRenderer::~GRenderer() {
LOG_DEBUG("Shutting down renderer...");
bgfx::shutdown();
}
void GRenderer::init() {
LOG_DEBUG("Initializing the GRenderer...");
this->bgfx_init();
this->shader_init();
}
void GRenderer::bgfx_init() {
// Call bgfx::renderFrame before bgfx::init to signal to bgfx not to create a
// render thread. Most graphics APIs must be used on the same thread that
// created the window.
bgfx::renderFrame();
bgfx::PlatformData pd;
pd.ndt = glfwGetX11Display();
pd.nwh = (void *)(uintptr_t)glfwGetX11Window(this->window->getWindow());
bgfx::Init init;
init.type = bgfx::RendererType::Count;
init.resolution.width = this->window->getWidth();
init.resolution.height = this->window->getHeight();
init.resolution.reset = BGFX_RESET_VSYNC;
init.platformData = pd;
if (bgfx::init(init) != true) {
LOG_ERROR("Failed to initialize bgfx.");
glfwTerminate();
throw std::runtime_error("Failed to initialize bgfx.");
}
/*
bgfx::setDebug(BGFX_DEBUG_TEXT);
bgfx::setViewClear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x443355FF, 1.0f,
0);
bgfx::setViewRect(0, 0, 0, this->window->getWidth(),
this->window->getHeight());
bgfx::touch(0);
*/
// Todo move this to some fancy class
static bgfx::VertexLayout layout;
this->layout = layout;
this->layout.begin()
.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
.end();
}
void GRenderer::shader_init() {
LOG_DEBUG("Loading shaders...");
LOG_DEBUG("Galaxy shader bin: " GALAXY_SHADER_BIN_DIR);
const char *path_v = GALAXY_SHADER_BIN_DIR "/glsl/v_simple.sc.bin";
const char *path_f = GALAXY_SHADER_BIN_DIR "/glsl/f_simple.sc.bin";
this->vsh = this->load_shader(path_v);
this->fsh = this->load_shader(path_f);
this->vbh = bgfx::createVertexBuffer(
// bgfx::makeRef(this->vertexes, sizeof(*this->vertexes)), this->layout);
bgfx::makeRef(&st_vertexes, sizeof(st_vertexes)), this->layout);
this->ibh = bgfx::createIndexBuffer(
// bgfx::makeRef(this->tri_list, sizeof(*this->tri_list)));
bgfx::makeRef(&st_tri_list, sizeof(st_tri_list)));
this->program = bgfx::createProgram(this->vsh, this->fsh, true);
// Reset window
bgfx::reset(this->window->getWidth(), this->window->getHeight(), BGFX_RESET_VSYNC);
// Enable debug text.
bgfx::setDebug(BGFX_DEBUG_TEXT /*| BGFX_DEBUG_STATS*/);
// Set view rectangle for 0th view
bgfx::setViewRect(0, 0, 0, uint16_t(this->window->getWidth()), uint16_t(this->window->getHeight()));
// Clear the view rect
bgfx::setViewClear(0,
BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH,
0x443355FF, 1.0f, 0);
}
bgfx::ShaderHandle GRenderer::load_shader(const char *name) {
char *data = new char[4098];
std::ifstream file;
size_t file_size;
file.open(name);
if (file.is_open()) {
// Get file size
file.seekg(0, std::ios::end);
file_size = file.tellg();
file.seekg(0, std::ios::beg);
file.read(data, file_size);
file.close();
} else {
delete[] data;
throw std::runtime_error(std::string("Failed to open shader file: ") +
std::string(name));
}
// create bgfx::Memory object and create shader from it
const bgfx::Memory *mem = bgfx::copy(data, file_size + 1);
mem->data[mem->size - 1] = '\0';
bgfx::ShaderHandle handle = bgfx::createShader(mem);
bgfx::setName(handle, name);
delete[] data;
return handle;
}
void GRenderer::update() {
LOG_DEBUG("Starting rendening update loop...");
const bx::Vec3 at = {0.0f, 0.0f, 0.0f};
const bx::Vec3 eye = {0.0f, 0.0f, 10.0f};
// Set view and projection matrix for view 0.
float view[16];
bx::mtxLookAt(view, eye, at);
float proj[16];
bx::mtxProj(proj, 60.0f,
float(this->window->getWidth()) /
float(this->window->getHeight()),
0.1f, 100.0f, bgfx::getCaps()->homogeneousDepth);
bgfx::setViewTransform(0, view, proj);
// Set view 0 default viewport.
bgfx::setViewRect(0, 0, 0, this->window->getWidth(),
this->window->getHeight());
bgfx::touch(0);
float mtx[16];
bx::mtxRotateY(mtx, 0.0f);
// position x,y,z
mtx[12] = 0.0f;
mtx[13] = 0.0f;
mtx[14] = 0.0f;
// Set model matrix for rendering.
bgfx::setTransform(mtx);
// Set vertex and index buffer.
bgfx::setVertexBuffer(0, this->vbh);
bgfx::setIndexBuffer(this->ibh);
// Set render states.
bgfx::setState(BGFX_STATE_DEFAULT);
// Submit primitive for rendering to view 0.
bgfx::submit(0, this->program);
LOG_DEBUG("Rendering...");
bgfx::frame();
}
+10
View File
@@ -0,0 +1,10 @@
#include <cstdlib>
#include <fstream>
#include "bgfx/bgfx.h"
#include "logger.h"
#include "gshader.h"
void GShader::init() {
};
+40
View File
@@ -0,0 +1,40 @@
#include "GLFW/glfw3.h"
#include "gwindow.h"
// TODO change this to utilize Logger
static void glfw_errorCallback(int error, const char *description) {
fprintf(stderr, "GLFW error, %d: %s\n", error, description);
}
void GWindow::init() {
LOG_DEBUG("Initializing the GWindow...");
glfwSetErrorCallback(glfw_errorCallback);
glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11);
if (!glfwInit()) {
LOG_ERROR("Failed to initialize GLFW."); // TODO move to caller
throw std::runtime_error("Failed to initialize GLFW.");
}
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
this->window =
glfwCreateWindow(this->width, this->height, "Galaxy-engine", NULL, NULL);
if (this->window == NULL) {
LOG_ERROR("Failed to create GLFW window."); // TODO move to caller
glfwTerminate();
throw std::runtime_error("Failed to create GLFW window.");
}
}
GWindow::~GWindow() {
LOG_DEBUG("Shutting down glfw window...");
glfwTerminate();
}
void GWindow::processInput() {
if (glfwGetKey(this->getWindow(), GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(this->getWindow(), true);
}
+33
View File
@@ -0,0 +1,33 @@
#include <iostream>
#include <string>
#include "logger.h"
#define TERMINAL_COLOR_PRE(col) "\033[" #col "m"
#define TERMINAL_COLOR_END "\033[0m"
Logger::Logger() : outputDest(&std::cout) {}
Logger::Logger(std::ostream *oDest) : outputDest(oDest) {}
Logger::Logger(const Logger &old_logger) {
this->outputDest = old_logger.outputDest;
}
void Logger::info(const std::string msg) {
*(this->outputDest) << TERMINAL_COLOR_PRE(36) << "[INFO]\t"
<< TERMINAL_COLOR_END << msg << std::endl;
}
void Logger::debug(const std::string msg) {
*(this->outputDest) << TERMINAL_COLOR_PRE(35) << "[DEBUG]\t"
<< TERMINAL_COLOR_END << msg << std::endl;
}
void Logger::error(const std::string msg) {
*(this->outputDest) << TERMINAL_COLOR_PRE(31) << "[ERROR]\t"
<< TERMINAL_COLOR_END << msg << std::endl;
}
void Logger::warn(const std::string msg) {
*(this->outputDest) << TERMINAL_COLOR_PRE(33) << "[WARN]\t"
<< TERMINAL_COLOR_END << msg << std::endl;
}
+5 -91
View File
@@ -1,94 +1,8 @@
#include <iostream> #include "galaxy.h"
#define BX_CONFIG_DEBUG 1 int main(int argc, char *args[]) {
#include "bx/bx.h" Galaxy engine = Galaxy();
#include "bgfx/bgfx.h" engine.init();
#include "bgfx/platform.h" engine.run();
#include "GLFW/glfw3.h"
#define GLFW_EXPOSE_NATIVE_X11
#include "GLFW/glfw3native.h"
const int W_WIDTH = 800;
const int W_HEIGHT = 600;
static void glfw_errorCallback(int error, const char *description)
{
fprintf(stderr, "GLFW error, %d: %s\n", error, description);
}
void processInput(GLFWwindow *window)
{
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
int main (int argc, char* args[])
{
std::cout << "Starting the engine..." << std::endl;
glfwSetErrorCallback(glfw_errorCallback);
glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11);
if (!glfwInit())
{
std::cout << "Failed to initialize GLFW" << std::endl;
return -1;
}
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(W_WIDTH, W_HEIGHT, "Galaxy-engine", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
// Call bgfx::renderFrame before bgfx::init to signal to bgfx not to create a render thread.
// Most graphics APIs must be used on the same thread that created the window.
bgfx::renderFrame();
bgfx::PlatformData pd;
pd.ndt = glfwGetX11Display();
pd.nwh = (void *)(uintptr_t) glfwGetX11Window(window);
bgfx::Init init;
init.type = bgfx::RendererType::Count;
init.resolution.width = W_WIDTH;
init.resolution.height = W_HEIGHT;
init.resolution.reset = BGFX_RESET_VSYNC;
init.platformData = pd;
if (bgfx::init(init) != true)
{
std::cout << "Failed to initialize bgfx" << std::endl;
glfwTerminate();
return -1;
}
bgfx::setDebug(BGFX_DEBUG_TEXT);
bgfx::setViewClear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x443355FF, 1.0f, 0);
bgfx::setViewRect(0, 0, 0, W_WIDTH, W_HEIGHT);
std::cout << "Initialization done." << std::endl;
while(!glfwWindowShouldClose(window))
{
processInput(window);
bgfx::touch(0);
bgfx::frame();
glfwPollEvents();
}
bgfx::shutdown();
glfwTerminate();
return 0; return 0;
} }
+8
View File
@@ -0,0 +1,8 @@
$input v_color0
#include <bgfx_shader.sh>
void main()
{
gl_FragColor = v_color0;
}
+10
View File
@@ -0,0 +1,10 @@
$input a_position, a_color0
$output v_color0
#include <bgfx_shader.sh>
void main()
{
gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0));
v_color0 = a_color0;
}
+4
View File
@@ -0,0 +1,4 @@
vec4 v_color0 : COLOR0;
vec3 a_position : POSITION;
vec4 a_color0 : COLOR0;
View File
+10
View File
@@ -0,0 +1,10 @@
#include "bgfx/bgfx.h"
#include "vertex.h"
void PosColVertex::init() {
this->layout.begin()
.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
.end();
}
View File