This commit is contained in:
tavo 2025-10-30 13:44:14 -06:00
parent fc862a279f
commit ede68286df

188
skr/skr.h
View file

@ -197,9 +197,8 @@ typedef struct SkrShader {
const char* Path; const char* Path;
} SkrShader; } SkrShader;
static SkrShader skr_fps_camera_vert = { static char* skr_camera_3d_vert =
GL_VERTEX_SHADER, "#version 330 core\n"
(char*){"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n" "layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec2 aTexCoord;\n" "layout (location = 1) in vec2 aTexCoord;\n"
"out vec2 TexCoord;\n" "out vec2 TexCoord;\n"
@ -210,8 +209,7 @@ static SkrShader skr_fps_camera_vert = {
"gl_Position = projection * view * model * vec4(aPos, " "gl_Position = projection * view * model * vec4(aPos, "
"1.0f);\n" "1.0f);\n"
"TexCoord = vec2(aTexCoord.x, aTexCoord.y);\n" "TexCoord = vec2(aTexCoord.x, aTexCoord.y);\n"
"}\n"}, "}\n";
NULL};
/** /**
* @brief Vertex structure used by the rendering engine. * @brief Vertex structure used by the rendering engine.
@ -421,9 +419,6 @@ 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;
SkrTexture* Textures; /*!< Array of textures used by model's meshes. */
unsigned int TextureCount;
char* Path; /*!< Filesystem path of the model file. */ char* Path; /*!< Filesystem path of the model file. */
} SkrModel; } SkrModel;
@ -482,6 +477,10 @@ typedef struct SkrState {
unsigned int ProgramCount; unsigned int ProgramCount;
} SkrState; } SkrState;
typedef enum SkrCameraType {
SKR_CAMERA_3D,
} SkrCameraType;
/** /**
* @brief First-person camera structure. * @brief First-person camera structure.
* *
@ -504,6 +503,9 @@ typedef struct SkrCamera {
float LastY; /*!< Last cursor Y position. */ float LastY; /*!< Last cursor Y position. */
bool FirstMouse; /*!< Whether the first mouse movement has been bool FirstMouse; /*!< Whether the first mouse movement has been
captured. */ captured. */
SkrCameraType Type;
bool Initialized; bool Initialized;
} SkrCamera; } SkrCamera;
@ -512,13 +514,19 @@ typedef struct SkrCamera {
.Position = {0.0f, 0.0f, 3.0f}, \ .Position = {0.0f, 0.0f, 3.0f}, \
.Front = {0.0f, 0.0f, -1.0f}, \ .Front = {0.0f, 0.0f, -1.0f}, \
.Up = {0.0f, 1.0f, 0.0f}, \ .Up = {0.0f, 1.0f, 0.0f}, \
\
.Yaw = -90.0f, \ .Yaw = -90.0f, \
.Pitch = 0.0f, \ .Pitch = 0.0f, \
.FOV = 70.0f, \ .FOV = 70.0f, \
\
.Sensitivity = 0.1f, \ .Sensitivity = 0.1f, \
.LastX = 400.0f, \ .LastX = 400.0f, \
.LastY = 300.0f, \ .LastY = 300.0f, \
.FirstMouse = true, \ .FirstMouse = true, \
\
.Type = SKR_CAMERA_3D, \
\
.Initialized = true, \
}) })
extern SkrCamera* g_skr_camera; extern SkrCamera* g_skr_camera;
@ -916,13 +924,15 @@ static inline GLuint m_skr_gl_create_program(const GLuint* shaders,
* @return Program ID, or 0 on failure. * @return Program ID, or 0 on failure.
*/ */
static inline GLuint static inline GLuint
m_skr_gl_create_program_from_shaders(const SkrShader* shaders_input, m_skr_gl_create_program_from_shaders(const SkrShader* shader_array,
const size_t count) { const size_t size) {
if (!shaders_input || count == 0) { if (!shader_array || size == 0) {
m_skr_last_error_set("either shaders_input != 1 or count == 0"); m_skr_last_error_set("either shaders_input != 1 or count == 0");
return 0; return 0;
} }
const size_t count = size / sizeof(SkrShader);
GLuint* shaders = (GLuint*)malloc(sizeof(GLuint) * count); GLuint* shaders = (GLuint*)malloc(sizeof(GLuint) * count);
if (!shaders) { if (!shaders) {
m_skr_last_error_set("shaders_input == NULL"); m_skr_last_error_set("shaders_input == NULL");
@ -930,7 +940,7 @@ m_skr_gl_create_program_from_shaders(const SkrShader* shaders_input,
} }
for (size_t i = 0; i < count; ++i) { for (size_t i = 0; i < count; ++i) {
const SkrShader* s = &shaders_input[i]; const SkrShader* s = &shader_array[i];
GLuint shader = 0; GLuint shader = 0;
if (s->Source) { if (s->Source) {
@ -1077,6 +1087,27 @@ 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) {
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); glUseProgram(mesh->Backend.GL.Program);
glBindVertexArray(mesh->VAO); glBindVertexArray(mesh->VAO);
glDrawArrays(GL_TRIANGLES, 0, mesh->VertexCount); glDrawArrays(GL_TRIANGLES, 0, mesh->VertexCount);
@ -1265,6 +1296,54 @@ static inline int SkrWindowShouldClose(SkrWindow* w) {
return 0; return 0;
} }
static inline void SkrRendererInit(SkrState* s) {
if (!s)
return;
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;
@ -1316,7 +1395,7 @@ static inline GLuint m_skr_gl_triangle(SkrState* s) {
}; };
mesh.Backend.GL.Program = mesh.Backend.GL.Program =
m_skr_gl_create_program_from_shaders(shaders, 2); m_skr_gl_create_program_from_shaders(shaders, sizeof(shaders));
glUseProgram(mesh.Backend.GL.Program); glUseProgram(mesh.Backend.GL.Program);
glGenVertexArrays(1, &mesh.VAO); glGenVertexArrays(1, &mesh.VAO);
@ -1355,8 +1434,6 @@ static inline void SkrTriangle(SkrState* s) {
} }
} }
static inline void SkrInitCamera(SkrState* s, SkrShader vert) {}
static inline void SkrCaptureCursor(SkrState* s) { static inline void SkrCaptureCursor(SkrState* s) {
if (s->Window->Backend.Type == SKR_BACKEND_WINDOW_GLFW) { if (s->Window->Backend.Type == SKR_BACKEND_WINDOW_GLFW) {
glfwSetInputMode(s->Window->Backend.Handler.GLFW, GLFW_CURSOR, glfwSetInputMode(s->Window->Backend.Handler.GLFW, GLFW_CURSOR,
@ -1364,6 +1441,87 @@ static inline void SkrCaptureCursor(SkrState* s) {
} }
} }
static inline void m_skr_gl_mesh_init(SkrMesh* m) {
if (!m || !m->Vertices || m->VertexCount == 0) {
m_skr_last_error_set("Invalid mesh: missing vertices or count");
return;
}
glGenVertexArrays(1, &m->VAO);
glGenBuffers(1, &m->VBO);
glBindVertexArray(m->VAO);
glBindBuffer(GL_ARRAY_BUFFER, m->VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(SkrVertex) * m->VertexCount,
m->Vertices, GL_STATIC_DRAW);
// vertex positions
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(SkrVertex),
(void*)0);
// vertex normals
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(SkrVertex),
(void*)offsetof(SkrVertex, Normal));
// vertex texture coords
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(SkrVertex),
(void*)offsetof(SkrVertex, UV));
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();
}
/**
* @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