aaaaaa
This commit is contained in:
parent
ede68286df
commit
784a9ad1bd
1 changed files with 112 additions and 310 deletions
422
skr/skr.h
422
skr/skr.h
|
|
@ -36,10 +36,10 @@ extern "C" {
|
||||||
/**
|
/**
|
||||||
* @brief Identifies the type of graphics API backend in use.
|
* @brief Identifies the type of graphics API backend in use.
|
||||||
*/
|
*/
|
||||||
typedef enum SkrApiBackendType {
|
typedef enum SkrAPIBackendType {
|
||||||
SKR_BACKEND_API_GL, /*!< OpenGL API. */
|
SKR_BACKEND_API_GL, /*!< OpenGL API. */
|
||||||
SKR_BACKEND_API_VK, /*!< Vulkan API. */
|
SKR_BACKEND_API_VK, /*!< Vulkan API. */
|
||||||
} SkrApiBackendType;
|
} SkrAPIBackendType;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* You can control which graphics API SKR uses by defining
|
* You can control which graphics API SKR uses by defining
|
||||||
|
|
@ -64,9 +64,6 @@ typedef enum SkrApiBackendType {
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Default API if none was specified: GL */
|
|
||||||
#define SKR_BACKEND_API SKR_BACKEND_API_GL
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#if !defined(VULKAN_H_)
|
#if !defined(VULKAN_H_)
|
||||||
|
|
@ -176,9 +173,10 @@ typedef struct SkrShader {
|
||||||
/**
|
/**
|
||||||
* @brief Shader type.
|
* @brief Shader type.
|
||||||
*
|
*
|
||||||
* OpenGL shader type enum (e.g. GL_VERTEX_SHADER, GL_FRAGMENT_SHADER).
|
* Can be used as OpenGL shader type enum (e.g. GL_VERTEX_SHADER,
|
||||||
|
* GL_FRAGMENT_SHADER).
|
||||||
*/
|
*/
|
||||||
const unsigned int Type;
|
unsigned int Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief GLSL source code (optional).
|
* @brief GLSL source code (optional).
|
||||||
|
|
@ -186,7 +184,7 @@ typedef struct SkrShader {
|
||||||
* If provided, the shader will be compiled directly from this string in
|
* If provided, the shader will be compiled directly from this string in
|
||||||
* memory. May be NULL if the shader is loaded from a file.
|
* memory. May be NULL if the shader is loaded from a file.
|
||||||
*/
|
*/
|
||||||
const char* Source;
|
const char* GLSL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Path to shader file (optional).
|
* @brief Path to shader file (optional).
|
||||||
|
|
@ -197,19 +195,22 @@ typedef struct SkrShader {
|
||||||
const char* Path;
|
const char* Path;
|
||||||
} SkrShader;
|
} SkrShader;
|
||||||
|
|
||||||
static char* skr_camera_3d_vert =
|
typedef struct SkrShaderProgram {
|
||||||
"#version 330 core\n"
|
SkrShader* Shaders;
|
||||||
"layout (location = 0) in vec3 aPos;\n"
|
unsigned int ShaderCount;
|
||||||
"layout (location = 1) in vec2 aTexCoord;\n"
|
/**
|
||||||
"out vec2 TexCoord;\n"
|
* @brief Backend-specific rendering data.
|
||||||
"uniform mat4 model;\n"
|
*
|
||||||
"uniform mat4 view;\n"
|
* Tagged union that stores handles or objects specific to the graphics
|
||||||
"uniform mat4 projection;\n"
|
* API backend in use. Only the member corresponding to the current
|
||||||
"void main() {\n"
|
* backend type is valid.
|
||||||
"gl_Position = projection * view * model * vec4(aPos, "
|
*/
|
||||||
"1.0f);\n"
|
union {
|
||||||
"TexCoord = vec2(aTexCoord.x, aTexCoord.y);\n"
|
struct {
|
||||||
"}\n";
|
GLuint ID;
|
||||||
|
} GL;
|
||||||
|
} Backend;
|
||||||
|
} SkrShaderProgram;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Vertex structure used by the rendering engine.
|
* @brief Vertex structure used by the rendering engine.
|
||||||
|
|
@ -302,13 +303,6 @@ typedef enum SkrTextureType {
|
||||||
* material properties (see @ref SkrTextureType).
|
* material properties (see @ref SkrTextureType).
|
||||||
*/
|
*/
|
||||||
typedef struct SkrTexture {
|
typedef struct SkrTexture {
|
||||||
/**
|
|
||||||
* @brief OpenGL texture object ID.
|
|
||||||
*
|
|
||||||
* Assigned by glGenTextures() and used to bind this texture to the GPU.
|
|
||||||
*/
|
|
||||||
unsigned int ID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Texture semantic type.
|
* @brief Texture semantic type.
|
||||||
*
|
*
|
||||||
|
|
@ -333,6 +327,12 @@ typedef struct SkrTexture {
|
||||||
* Original file location of the texture (e.g. "assets/diffuse.png").
|
* Original file location of the texture (e.g. "assets/diffuse.png").
|
||||||
*/
|
*/
|
||||||
char* Path;
|
char* Path;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
GLuint ID;
|
||||||
|
} GL;
|
||||||
|
} Backend;
|
||||||
} SkrTexture;
|
} SkrTexture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -380,32 +380,7 @@ typedef struct SkrMesh {
|
||||||
*/
|
*/
|
||||||
unsigned int Indices;
|
unsigned int Indices;
|
||||||
|
|
||||||
/**
|
SkrShaderProgram* Program;
|
||||||
* @brief Associated textures.
|
|
||||||
*
|
|
||||||
* Pointer to an array of @ref SkrTexture objects that define the
|
|
||||||
* materials of this mesh.
|
|
||||||
*/
|
|
||||||
SkrTexture* Textures;
|
|
||||||
unsigned int TextureCount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Backend-specific rendering data.
|
|
||||||
*
|
|
||||||
* Tagged union that stores handles or objects specific to the graphics
|
|
||||||
* API backend in use. Only the member corresponding to the current
|
|
||||||
* backend type is valid.
|
|
||||||
*/
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
GLuint Program;
|
|
||||||
} GL;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
VkPipeline Pipeline;
|
|
||||||
VkPipelineLayout Layout;
|
|
||||||
} VK;
|
|
||||||
} Backend;
|
|
||||||
} SkrMesh;
|
} SkrMesh;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -419,7 +394,16 @@ typedef struct SkrModel {
|
||||||
SkrMesh* Meshes; /*!< Array of meshes that compose the model. */
|
SkrMesh* Meshes; /*!< Array of meshes that compose the model. */
|
||||||
unsigned int MeshCount;
|
unsigned int MeshCount;
|
||||||
|
|
||||||
char* Path; /*!< Filesystem path of the model file. */
|
/**
|
||||||
|
* @brief Associated textures.
|
||||||
|
*
|
||||||
|
* Pointer to an array of @ref SkrTexture objects that define the
|
||||||
|
* materials of this mesh.
|
||||||
|
*/
|
||||||
|
SkrTexture* Textures;
|
||||||
|
unsigned int TextureCount;
|
||||||
|
|
||||||
|
char* Directory; /*!< Filesystem path of the model directory. */
|
||||||
} SkrModel;
|
} SkrModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -460,27 +444,6 @@ typedef struct SkrWindow {
|
||||||
SkrWindowBackend Backend; /*!< Backend type and handle. */
|
SkrWindowBackend Backend; /*!< Backend type and handle. */
|
||||||
} SkrWindow;
|
} SkrWindow;
|
||||||
|
|
||||||
typedef struct SkrShaderProgram {
|
|
||||||
GLuint ID;
|
|
||||||
char* Name;
|
|
||||||
SkrShader* Shaders;
|
|
||||||
unsigned int ShaderCount;
|
|
||||||
} SkrShaderProgram;
|
|
||||||
|
|
||||||
typedef struct SkrState {
|
|
||||||
SkrWindow* Window;
|
|
||||||
|
|
||||||
SkrModel* Models;
|
|
||||||
unsigned int ModelCount;
|
|
||||||
|
|
||||||
SkrShaderProgram* Programs;
|
|
||||||
unsigned int ProgramCount;
|
|
||||||
} SkrState;
|
|
||||||
|
|
||||||
typedef enum SkrCameraType {
|
|
||||||
SKR_CAMERA_3D,
|
|
||||||
} SkrCameraType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief First-person camera structure.
|
* @brief First-person camera structure.
|
||||||
*
|
*
|
||||||
|
|
@ -497,18 +460,26 @@ typedef struct SkrCamera {
|
||||||
float Yaw;
|
float Yaw;
|
||||||
float Pitch;
|
float Pitch;
|
||||||
float FOV;
|
float FOV;
|
||||||
|
float Zoom;
|
||||||
|
|
||||||
float Sensitivity;
|
float Sensitivity;
|
||||||
float LastX; /*!< Last cursor X position. */
|
float Speed;
|
||||||
float LastY; /*!< Last cursor Y position. */
|
|
||||||
bool FirstMouse; /*!< Whether the first mouse movement has been
|
|
||||||
captured. */
|
|
||||||
|
|
||||||
SkrCameraType Type;
|
|
||||||
|
|
||||||
bool Initialized;
|
|
||||||
} SkrCamera;
|
} SkrCamera;
|
||||||
|
|
||||||
|
static char* skr_camera_3d_vert =
|
||||||
|
"#version 330 core\n"
|
||||||
|
"layout (location = 0) in vec3 aPos;\n"
|
||||||
|
"layout (location = 1) in vec2 aTexCoord;\n"
|
||||||
|
"out vec2 TexCoord;\n"
|
||||||
|
"uniform mat4 model;\n"
|
||||||
|
"uniform mat4 view;\n"
|
||||||
|
"uniform mat4 projection;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
"gl_Position = projection * view * model * vec4(aPos, "
|
||||||
|
"1.0f);\n"
|
||||||
|
"TexCoord = vec2(aTexCoord.x, aTexCoord.y);\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
#define SkrDefaultFPSCamera \
|
#define SkrDefaultFPSCamera \
|
||||||
(&(SkrCamera){ \
|
(&(SkrCamera){ \
|
||||||
.Position = {0.0f, 0.0f, 3.0f}, \
|
.Position = {0.0f, 0.0f, 3.0f}, \
|
||||||
|
|
@ -518,18 +489,24 @@ typedef struct SkrCamera {
|
||||||
.Yaw = -90.0f, \
|
.Yaw = -90.0f, \
|
||||||
.Pitch = 0.0f, \
|
.Pitch = 0.0f, \
|
||||||
.FOV = 70.0f, \
|
.FOV = 70.0f, \
|
||||||
|
.Zoom = 1.0f, \
|
||||||
\
|
\
|
||||||
.Sensitivity = 0.1f, \
|
.Sensitivity = 0.1f, \
|
||||||
.LastX = 400.0f, \
|
.Speed = 0.1f, \
|
||||||
.LastY = 300.0f, \
|
|
||||||
.FirstMouse = true, \
|
|
||||||
\
|
|
||||||
.Type = SKR_CAMERA_3D, \
|
|
||||||
\
|
|
||||||
.Initialized = true, \
|
|
||||||
})
|
})
|
||||||
|
|
||||||
extern SkrCamera* g_skr_camera;
|
typedef struct SkrState {
|
||||||
|
SkrWindow* Window;
|
||||||
|
|
||||||
|
SkrModel* Models;
|
||||||
|
unsigned int ModelCount;
|
||||||
|
|
||||||
|
SkrCamera* Camera;
|
||||||
|
|
||||||
|
union {
|
||||||
|
bool GL;
|
||||||
|
} Backend;
|
||||||
|
} SkrState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
|
|
@ -691,49 +668,6 @@ static inline void m_skr_gl_glfw_framebuffer_size_callback(GLFWwindow* window,
|
||||||
m_skr_last_error_clear();
|
m_skr_last_error_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void m_skr_gl_glfw_mouse_callback(GLFWwindow* window,
|
|
||||||
double xposIn, double yposIn) {
|
|
||||||
float xpos = xposIn;
|
|
||||||
float ypos = yposIn;
|
|
||||||
|
|
||||||
if (g_skr_camera->FirstMouse) {
|
|
||||||
g_skr_camera->LastX = xpos;
|
|
||||||
g_skr_camera->LastY = ypos;
|
|
||||||
g_skr_camera->FirstMouse = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
float xoffset = xpos - g_skr_camera->LastX;
|
|
||||||
float yoffset =
|
|
||||||
g_skr_camera->LastY -
|
|
||||||
ypos; // reversed since y-coordinates go from bottom to top
|
|
||||||
g_skr_camera->LastX = xpos;
|
|
||||||
g_skr_camera->LastY = ypos;
|
|
||||||
|
|
||||||
float sensitivity = g_skr_camera->Sensitivity;
|
|
||||||
xoffset *= sensitivity;
|
|
||||||
yoffset *= sensitivity;
|
|
||||||
|
|
||||||
g_skr_camera->Yaw += xoffset;
|
|
||||||
g_skr_camera->Pitch += yoffset;
|
|
||||||
|
|
||||||
// make sure that when pitch is out of bounds, screen doesn't get
|
|
||||||
// flipped
|
|
||||||
if (g_skr_camera->Pitch > 89.0f)
|
|
||||||
g_skr_camera->Pitch = 89.0f;
|
|
||||||
if (g_skr_camera->Pitch < -89.0f)
|
|
||||||
g_skr_camera->Pitch = -89.0f;
|
|
||||||
|
|
||||||
vec3 front = {0.0f, 0.0f, 0.0f};
|
|
||||||
|
|
||||||
front[0] = cosf(glm_rad(g_skr_camera->Yaw)) *
|
|
||||||
cosf(glm_rad(g_skr_camera->Pitch));
|
|
||||||
front[1] = sinf(glm_rad(g_skr_camera->Pitch));
|
|
||||||
front[2] = sinf(glm_rad(g_skr_camera->Yaw)) *
|
|
||||||
cosf(glm_rad(g_skr_camera->Pitch));
|
|
||||||
|
|
||||||
glm_vec3_normalize_to(front, g_skr_camera->Front);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
* @brief Initialize a GLFW window for OpenGL rendering.
|
* @brief Initialize a GLFW window for OpenGL rendering.
|
||||||
|
|
@ -768,12 +702,8 @@ static inline int m_skr_gl_glfw_init(SkrWindow* w) {
|
||||||
|
|
||||||
glfwSetFramebufferSizeCallback(w->Backend.Handler.GLFW,
|
glfwSetFramebufferSizeCallback(w->Backend.Handler.GLFW,
|
||||||
m_skr_gl_glfw_framebuffer_size_callback);
|
m_skr_gl_glfw_framebuffer_size_callback);
|
||||||
glfwMakeContextCurrent(w->Backend.Handler.GLFW);
|
|
||||||
|
|
||||||
if (g_skr_camera) {
|
glfwMakeContextCurrent(w->Backend.Handler.GLFW);
|
||||||
glfwSetCursorPosCallback(w->Backend.Handler.GLFW,
|
|
||||||
m_skr_gl_glfw_mouse_callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_skr_last_error_clear();
|
m_skr_last_error_clear();
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -943,8 +873,8 @@ m_skr_gl_create_program_from_shaders(const SkrShader* shader_array,
|
||||||
const SkrShader* s = &shader_array[i];
|
const SkrShader* s = &shader_array[i];
|
||||||
GLuint shader = 0;
|
GLuint shader = 0;
|
||||||
|
|
||||||
if (s->Source) {
|
if (s->GLSL) {
|
||||||
shader = m_skr_gl_create_shader(s->Type, s->Source);
|
shader = m_skr_gl_create_shader(s->Type, s->GLSL);
|
||||||
} else if (s->Path) {
|
} else if (s->Path) {
|
||||||
shader = m_skr_gl_create_shader_from_file(s->Type,
|
shader = m_skr_gl_create_shader_from_file(s->Type,
|
||||||
s->Path);
|
s->Path);
|
||||||
|
|
@ -980,25 +910,16 @@ m_skr_gl_create_program_from_shaders(const SkrShader* shader_array,
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
* @brief GL use an OpenGL shader program.
|
|
||||||
*/
|
|
||||||
static inline void m_skr_gl_shader_use(const GLuint program) {
|
|
||||||
glUseProgram(program);
|
|
||||||
m_skr_last_error_clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
* @brief GL destroy an OpenGL shader program.
|
* @brief GL destroy an OpenGL shader program.
|
||||||
*
|
*
|
||||||
* @param program Pointer to program ID. Resets to 0 on success.
|
* @param program Pointer to program ID. Resets to 0 on success.
|
||||||
*/
|
*/
|
||||||
static inline void m_skr_gl_shader_destroy(GLuint* program) {
|
static inline void m_skr_gl_shader_destroy(GLuint program) {
|
||||||
if (program && *program) {
|
if (program) {
|
||||||
glDeleteProgram(*program);
|
glDeleteProgram(program);
|
||||||
*program = 0;
|
program = 0;
|
||||||
m_skr_last_error_clear();
|
m_skr_last_error_clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1069,10 +990,6 @@ static inline void m_skr_gl_shader_set_mat4(const GLuint program,
|
||||||
|
|
||||||
static inline void m_skr_gl_renderer_init() {}
|
static inline void m_skr_gl_renderer_init() {}
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
* @brief GL clear screen (color + depth).
|
|
||||||
*/
|
|
||||||
static inline void m_skr_gl_renderer_render(SkrState* s) {
|
static inline void m_skr_gl_renderer_render(SkrState* s) {
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
|
@ -1087,28 +1004,7 @@ static inline void m_skr_gl_renderer_render(SkrState* s) {
|
||||||
if (mesh->VAO == 0 || mesh->VertexCount == 0)
|
if (mesh->VAO == 0 || mesh->VertexCount == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (g_skr_camera) {
|
glUseProgram(mesh->Program->Backend.GL.ID);
|
||||||
mat4 projection;
|
|
||||||
glm_perspective(
|
|
||||||
glm_rad(g_skr_camera->FOV),
|
|
||||||
(float)s->Window->Width /
|
|
||||||
(float)s->Window->Height,
|
|
||||||
0.1f, 100.0f, projection);
|
|
||||||
m_skr_gl_shader_set_mat4(
|
|
||||||
mesh->Backend.GL.Program, "projection",
|
|
||||||
projection);
|
|
||||||
|
|
||||||
vec3 center;
|
|
||||||
glm_vec3_add(g_skr_camera->Position,
|
|
||||||
g_skr_camera->Front, center);
|
|
||||||
mat4 view;
|
|
||||||
glm_lookat(g_skr_camera->Position, center,
|
|
||||||
g_skr_camera->Up, view);
|
|
||||||
m_skr_gl_shader_set_mat4(
|
|
||||||
mesh->Backend.GL.Program, "view", view);
|
|
||||||
}
|
|
||||||
|
|
||||||
glUseProgram(mesh->Backend.GL.Program);
|
|
||||||
glBindVertexArray(mesh->VAO);
|
glBindVertexArray(mesh->VAO);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, mesh->VertexCount);
|
glDrawArrays(GL_TRIANGLES, 0, mesh->VertexCount);
|
||||||
}
|
}
|
||||||
|
|
@ -1117,32 +1013,25 @@ static inline void m_skr_gl_renderer_render(SkrState* s) {
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
* @brief GL free VAO/VBO/EBO of a mesh.
|
|
||||||
*
|
|
||||||
* Usually called at shutdown, not per-frame.
|
|
||||||
*/
|
|
||||||
static inline void m_skr_gl_renderer_finalize(SkrState* s) {
|
static inline void m_skr_gl_renderer_finalize(SkrState* s) {
|
||||||
if (!s)
|
if (!s)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < s->ModelCount; ++i) {
|
for (unsigned int i = 0; i < s->ModelCount; ++i) {
|
||||||
SkrModel* model = &s->Models[i];
|
SkrModel* model = &s->Models[i];
|
||||||
|
|
||||||
|
if (model->Textures && model->TextureCount > 0) {
|
||||||
|
for (unsigned int t = 0; t < model->TextureCount; ++t) {
|
||||||
|
glDeleteTextures(
|
||||||
|
1, &model->Textures[t].Backend.GL.ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!model->Meshes)
|
if (!model->Meshes)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (unsigned int j = 0; j < model->MeshCount; ++j) {
|
for (unsigned int j = 0; j < model->MeshCount; ++j) {
|
||||||
SkrMesh* mesh = &model->Meshes[j];
|
SkrMesh* mesh = &model->Meshes[j];
|
||||||
|
|
||||||
if (mesh->Textures && mesh->TextureCount > 0) {
|
|
||||||
for (unsigned int t = 0; t < mesh->TextureCount;
|
|
||||||
++t) {
|
|
||||||
glDeleteTextures(1,
|
|
||||||
&mesh->Textures[t].ID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mesh->VAO)
|
if (mesh->VAO)
|
||||||
glDeleteVertexArrays(1, &mesh->VAO);
|
glDeleteVertexArrays(1, &mesh->VAO);
|
||||||
if (mesh->VBO)
|
if (mesh->VBO)
|
||||||
|
|
@ -1151,7 +1040,6 @@ static inline void m_skr_gl_renderer_finalize(SkrState* s) {
|
||||||
glDeleteBuffers(1, &mesh->EBO);
|
glDeleteBuffers(1, &mesh->EBO);
|
||||||
|
|
||||||
mesh->VAO = mesh->VBO = mesh->EBO = 0;
|
mesh->VAO = mesh->VBO = mesh->EBO = 0;
|
||||||
mesh->Backend.GL.Program = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1266,10 +1154,12 @@ static inline void m_skr_free_textures_2d(unsigned int* textures,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int SkrWindowInit(SkrWindow* w) {
|
static inline int m_skr_window_init(SkrState* s, int backend) {
|
||||||
if (SKR_BACKEND_API == SKR_BACKEND_API_GL) {
|
if (SKR_BACKEND_WINDOW == SKR_BACKEND_WINDOW_GLFW) {
|
||||||
if (SKR_BACKEND_WINDOW == SKR_BACKEND_WINDOW_GLFW) {
|
if (backend == SKR_BACKEND_API_GL) {
|
||||||
if (!m_skr_gl_glfw_init(w)) {
|
s->Backend.GL = true;
|
||||||
|
|
||||||
|
if (!m_skr_gl_glfw_init(s->Window)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1278,13 +1168,13 @@ static inline int SkrWindowInit(SkrWindow* w) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline SkrState SkrInit(SkrWindow* w) {
|
static inline SkrState SkrInit(SkrWindow* w, int backend) {
|
||||||
SkrState s = {0};
|
SkrState s = {0};
|
||||||
|
s.Window = w;
|
||||||
|
|
||||||
if (!SkrWindowInit(w))
|
if (!m_skr_window_init(&s, backend))
|
||||||
return (SkrState){0};
|
return (SkrState){0};
|
||||||
|
|
||||||
s.Window = w;
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1301,62 +1191,21 @@ static inline void SkrRendererInit(SkrState* s) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < s->ModelCount; ++i) {
|
|
||||||
SkrModel* model = &s->Models[i];
|
|
||||||
for (unsigned int j = 0; j < model->MeshCount; ++j) {
|
|
||||||
SkrMesh* mesh = &model->Meshes[j];
|
|
||||||
|
|
||||||
glGenVertexArrays(1, &mesh->VAO);
|
|
||||||
glGenBuffers(1, &mesh->VBO);
|
|
||||||
glBindVertexArray(mesh->VAO);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, mesh->VBO);
|
|
||||||
|
|
||||||
glBufferData(GL_ARRAY_BUFFER,
|
|
||||||
mesh->VertexCount * sizeof(SkrVertex),
|
|
||||||
mesh->Vertices, GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
glVertexAttribPointer(
|
|
||||||
0, 3, GL_FLOAT, GL_FALSE, sizeof(SkrVertex),
|
|
||||||
(void*)offsetof(SkrVertex, Position));
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
|
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,
|
|
||||||
sizeof(SkrVertex),
|
|
||||||
(void*)offsetof(SkrVertex, UV));
|
|
||||||
glEnableVertexAttribArray(1);
|
|
||||||
|
|
||||||
for (unsigned int t = 0; t < mesh->TextureCount; ++t) {
|
|
||||||
SkrTexture* tex = &mesh->Textures[t];
|
|
||||||
if (tex->Path && !tex->ID) {
|
|
||||||
unsigned int tex_id;
|
|
||||||
if (m_skr_gl_load_texture_2d_from_path(
|
|
||||||
tex->Path, &tex_id)) {
|
|
||||||
tex->ID = tex_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glUseProgram(mesh->Backend.GL.Program);
|
|
||||||
|
|
||||||
glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void SkrRendererRender(SkrState* s) {
|
static inline void SkrRendererRender(SkrState* s) {
|
||||||
if (!s || !s->Window)
|
if (!s || !s->Window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (SKR_BACKEND_API == SKR_BACKEND_API_GL) {
|
if (SKR_BACKEND_WINDOW == SKR_BACKEND_WINDOW_GLFW) {
|
||||||
if (SKR_BACKEND_WINDOW == SKR_BACKEND_WINDOW_GLFW) {
|
if (s->Backend.GL) {
|
||||||
m_skr_gl_glfw_renderer_render(s);
|
m_skr_gl_glfw_renderer_render(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void SkrFinalize(SkrState* s) {
|
static inline void SkrFinalize(SkrState* s) {
|
||||||
if (SKR_BACKEND_API == SKR_BACKEND_API_GL) {
|
if (s->Backend.GL) {
|
||||||
m_skr_gl_renderer_finalize(s);
|
m_skr_gl_renderer_finalize(s);
|
||||||
|
|
||||||
if (s->Window->Backend.Type == SKR_BACKEND_WINDOW_GLFW) {
|
if (s->Window->Backend.Type == SKR_BACKEND_WINDOW_GLFW) {
|
||||||
|
|
@ -1369,7 +1218,7 @@ static inline void SkrFinalize(SkrState* s) {
|
||||||
s->Window = NULL;
|
s->Window = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline GLuint m_skr_gl_triangle(SkrState* s) {
|
static inline void m_skr_gl_triangle(SkrState* s) {
|
||||||
static SkrMesh mesh = {0};
|
static SkrMesh mesh = {0};
|
||||||
static SkrModel model = {0};
|
static SkrModel model = {0};
|
||||||
|
|
||||||
|
|
@ -1394,9 +1243,9 @@ static inline GLuint m_skr_gl_triangle(SkrState* s) {
|
||||||
{GL_FRAGMENT_SHADER, triangle_frag, NULL},
|
{GL_FRAGMENT_SHADER, triangle_frag, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
mesh.Backend.GL.Program =
|
GLuint prog =
|
||||||
m_skr_gl_create_program_from_shaders(shaders, sizeof(shaders));
|
m_skr_gl_create_program_from_shaders(shaders, sizeof(shaders));
|
||||||
glUseProgram(mesh.Backend.GL.Program);
|
glUseProgram(prog);
|
||||||
|
|
||||||
glGenVertexArrays(1, &mesh.VAO);
|
glGenVertexArrays(1, &mesh.VAO);
|
||||||
glGenBuffers(1, &mesh.VBO);
|
glGenBuffers(1, &mesh.VBO);
|
||||||
|
|
@ -1418,18 +1267,21 @@ static inline GLuint m_skr_gl_triangle(SkrState* s) {
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
|
SkrShaderProgram program = {.Backend.GL.ID = prog};
|
||||||
|
|
||||||
mesh.VertexCount = 3;
|
mesh.VertexCount = 3;
|
||||||
|
mesh.Program = &program;
|
||||||
model.Meshes = &mesh;
|
model.Meshes = &mesh;
|
||||||
model.MeshCount = 1;
|
model.MeshCount = 1;
|
||||||
|
|
||||||
s->Models = &model;
|
s->Models = &model;
|
||||||
s->ModelCount = 1;
|
s->ModelCount = 1;
|
||||||
|
|
||||||
return mesh.Backend.GL.Program;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void SkrTriangle(SkrState* s) {
|
static inline void SkrTriangle(SkrState* s) {
|
||||||
if (SKR_BACKEND_API == SKR_BACKEND_API_GL) {
|
if (s->Backend.GL) {
|
||||||
m_skr_gl_triangle(s);
|
m_skr_gl_triangle(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1441,25 +1293,21 @@ static inline void SkrCaptureCursor(SkrState* s) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void m_skr_gl_mesh_init(SkrMesh* m) {
|
static inline void m_skr_gl_mesh_init(SkrMesh* m, SkrVertex* vertices,
|
||||||
if (!m || !m->Vertices || m->VertexCount == 0) {
|
size_t size) {
|
||||||
m_skr_last_error_set("Invalid mesh: missing vertices or count");
|
if (!vertices || size == 0) {
|
||||||
|
m_skr_last_error_set("missing vertices or size");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
glGenVertexArrays(1, &m->VAO);
|
glGenVertexArrays(1, &m->VAO);
|
||||||
|
|
||||||
glGenBuffers(1, &m->VBO);
|
glGenBuffers(1, &m->VBO);
|
||||||
|
|
||||||
glBindVertexArray(m->VAO);
|
glBindVertexArray(m->VAO);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, m->VBO);
|
glBindBuffer(GL_ARRAY_BUFFER, m->VBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, size, vertices, GL_STATIC_DRAW);
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(SkrVertex) * m->VertexCount,
|
|
||||||
m->Vertices, GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
// vertex positions
|
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
// vertex position
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(SkrVertex),
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(SkrVertex),
|
||||||
(void*)0);
|
(void*)0);
|
||||||
// vertex normals
|
// vertex normals
|
||||||
|
|
@ -1473,55 +1321,9 @@ static inline void m_skr_gl_mesh_init(SkrMesh* m) {
|
||||||
|
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
if (m->Textures && m->TextureCount > 0) {
|
|
||||||
for (unsigned int i = 0; i < m->TextureCount; ++i) {
|
|
||||||
SkrTexture* tex = &m->Textures[i];
|
|
||||||
|
|
||||||
if (!tex->Path) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int id = 0;
|
|
||||||
if (!m_skr_gl_load_texture_2d_from_path(tex->Path,
|
|
||||||
&id)) {
|
|
||||||
fprintf(stderr, "Failed to load texture: %s\n",
|
|
||||||
tex->Path);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
tex->ID = id;
|
|
||||||
tex->Type = (i == 0) ? SKR_TEXTURE_DIFFUSE
|
|
||||||
: SKR_TEXTURE_SPECULAR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_skr_last_error_clear();
|
m_skr_last_error_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Bind all textures of a mesh to consecutive texture units.
|
|
||||||
* Starts at GL_TEXTURE0 and binds each SkrTexture.ID in order.
|
|
||||||
*
|
|
||||||
* @param mesh The mesh whose textures to bind.
|
|
||||||
*/
|
|
||||||
static inline void m_skr_gl_mesh_bind_textures(const SkrMesh* mesh) {
|
|
||||||
if (!mesh || !mesh->Textures || mesh->TextureCount == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < mesh->TextureCount; ++i) {
|
|
||||||
const SkrTexture* tex = &mesh->Textures[i];
|
|
||||||
|
|
||||||
if (tex->ID == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0 + i); // activate unit N
|
|
||||||
glBindTexture(GL_TEXTURE_2D, tex->ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue