feat: implemented default shader

This commit is contained in:
Sara 2024-09-17 21:37:13 +02:00
parent fdc92c8c20
commit a0be00407f
10 changed files with 129 additions and 19 deletions

View file

@ -0,0 +1,20 @@
#version 330
in vec2 fragTexCoord; // texture coordinate
in vec3 fragNormal; // normal direction
uniform sampler2D texture0;
uniform vec4 colDiffuse;
out vec4 finalColor;
uniform vec3 lightDirection; // direction of light
uniform vec4 ambient;
void main() {
vec4 texelColor = texture(texture0, fragTexCoord);
vec3 light_dot = vec3(pow(dot(fragNormal, lightDirection)-0.2, 3.0));
finalColor = texelColor * colDiffuse * vec4(light_dot, 1.0);
finalColor += texelColor * (ambient/10.0) * colDiffuse;
finalColor = pow(finalColor, vec4(vec3(0.6), 1.0));
}

View file

@ -0,0 +1,25 @@
#version 330
// Input vertex attributes
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec3 vertexNormal;
in vec4 vertexColor;
// Input uniform values
uniform mat4 mvp;
uniform mat4 matModel;
// Output vertex attributes (to fragment shader)
out vec2 fragTexCoord;
out vec3 fragNormal;
void main()
{
// Send vertex attributes to fragment shader
fragTexCoord = vertexTexCoord;
fragNormal = normalize(vec3(matModel * vec4(vertexNormal, 1.0)));
// Calculate final vertex position
gl_Position = mvp*vec4(vertexPosition, 1.0);
}

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 496 B

View file

@ -25,6 +25,7 @@ impl_Renderable_for(MeshRenderEntity,
SceneNode *CreateMeshRenderEntity(char const *resource_path) { SceneNode *CreateMeshRenderEntity(char const *resource_path) {
MeshRenderEntity *self = new(MeshRenderEntity); MeshRenderEntity *self = new(MeshRenderEntity);
GetModelResource(resource_path, &self->model); GetModelResource(resource_path, &self->model);
GetShaderResource("default_shader", &self->shader);
return CreateSceneNode(MeshRenderEntity_as_SceneNodeEntity(self)); return CreateSceneNode(MeshRenderEntity_as_SceneNodeEntity(self));
} }
@ -36,15 +37,24 @@ void MeshRenderEntityEnterTree(MeshRenderEntity *self) {
SceneNodeEntity parent_entity = self->node->parent->entity; SceneNodeEntity parent_entity = self->node->parent->entity;
self->transform = TC_CAST(parent_entity, Transformable); self->transform = TC_CAST(parent_entity, Transformable);
LoadResource(self->model.handle); LoadResource(self->model.handle);
LoadResource(self->shader.handle);
Vector3 light_direction = Vector3Normalize((Vector3){1.f, 1.f, 0.f});
SetShaderValue(*self->shader.resource, GetShaderLocation(*self->shader.resource, "lightDirection"), &light_direction, SHADER_UNIFORM_VEC3);
SetShaderValue(*self->shader.resource, GetShaderLocation(*self->shader.resource, "ambient"), &BLACK, SHADER_UNIFORM_VEC4);
for(size_t i = 0; i < self->model.resource->materialCount; ++i)
self->model.resource->materials[i].shader = *self->shader.resource;
AddRenderable(MeshRenderEntity_as_Renderable(self)); AddRenderable(MeshRenderEntity_as_Renderable(self));
} }
void MeshRenderEntityExitTree(MeshRenderEntity *self) { void MeshRenderEntityExitTree(MeshRenderEntity *self) {
ReleaseResource(self->model.handle); ReleaseResource(self->model.handle);
ReleaseResource(self->shader.handle);
RemoveRenderable(MeshRenderEntity_as_Renderable(self)); RemoveRenderable(MeshRenderEntity_as_Renderable(self));
} }
void MeshRenderEntityDraw(MeshRenderEntity *self) { void MeshRenderEntityDraw(MeshRenderEntity *self) {
self->model.resource->transform = TransformGetMatrix(self->transform.tc->get_global_transform(self->transform.data)); self->model.resource->transform = TransformGetMatrix(self->transform.tc->get_global_transform(self->transform.data));
DrawModel(*self->model.resource, (Vector3){0.f, 0.f, 0.f}, 1.f, WHITE); BeginShaderMode(*self->shader.resource);
DrawModel(*self->model.resource, Vector3Zero(), 1.0f, WHITE);
EndShaderMode();
} }

View file

@ -12,6 +12,7 @@ typedef struct MeshRenderEntity {
SceneNode *node; SceneNode *node;
Transformable transform; Transformable transform;
ModelResource model; ModelResource model;
ShaderResource shader;
} MeshRenderEntity; } MeshRenderEntity;
extern SceneNode *CreateMeshRenderEntity(char const *resource_path); extern SceneNode *CreateMeshRenderEntity(char const *resource_path);

View file

@ -8,7 +8,7 @@
char const *RESOURCE_DIRECTORY = "resources"; char const *RESOURCE_DIRECTORY = "resources";
typedef enum ResourceType { typedef enum ResourceType {
RESOURCE_MODEL, RESOURCE_TEXTURE, RESOURCE_MODEL, RESOURCE_TEXTURE, RESOURCE_SHADER,
RESOURCE_MAX RESOURCE_MAX
} ResourceType; } ResourceType;
@ -21,6 +21,7 @@ typedef struct ResourceContainer {
union { union {
Model model; Model model;
Texture texture; Texture texture;
Shader shader;
}; };
} ResourceContainer; } ResourceContainer;
@ -31,9 +32,11 @@ static void Internal_LoadModelResource(ResourceContainer *resource);
static void Internal_UnloadModelResource(ResourceContainer *resource); static void Internal_UnloadModelResource(ResourceContainer *resource);
static void Internal_LoadTextureResource(ResourceContainer *resource); static void Internal_LoadTextureResource(ResourceContainer *resource);
static void Internal_UnloadTextureResource(ResourceContainer *resource); static void Internal_UnloadTextureResource(ResourceContainer *resource);
static void Internal_LoadShaderResource(ResourceContainer *resource);
static void Internal_UnloadShaderResource(ResourceContainer *resource);
LoadResourceFn g_load_functions[] = {Internal_LoadModelResource, Internal_LoadTextureResource}; LoadResourceFn g_load_functions[] = {Internal_LoadModelResource, Internal_LoadTextureResource, Internal_LoadShaderResource};
UnloadResourceFn g_unload_functions[] = {Internal_UnloadModelResource, Internal_UnloadTextureResource}; UnloadResourceFn g_unload_functions[] = {Internal_UnloadModelResource, Internal_UnloadTextureResource, Internal_UnloadShaderResource};
static HashMap g_resource_map; static HashMap g_resource_map;
static FilePathList g_resource_files; static FilePathList g_resource_files;
@ -52,6 +55,9 @@ static ResourceType ResourceGetTypeFromPath(char const *path) {
// Model files // Model files
if(IsFileExtension(path, ".glb")) return RESOURCE_MODEL; if(IsFileExtension(path, ".glb")) return RESOURCE_MODEL;
if(IsFileExtension(path, ".gltf")) return RESOURCE_MODEL; if(IsFileExtension(path, ".gltf")) return RESOURCE_MODEL;
// Shader files
if(IsFileExtension(path, ".fg")) return RESOURCE_SHADER;
if(IsFileExtension(path, ".vs")) return RESOURCE_SHADER;
return RESOURCE_MAX; return RESOURCE_MAX;
} }
@ -85,13 +91,23 @@ void Internal_IndexResourceDirectory() {
.is_loaded = false, .is_loaded = false,
.use_counter = 0, .use_counter = 0,
.path = g_resource_files.paths[i], .path = g_resource_files.paths[i],
.name = GetFileName(g_resource_files.paths[i]), .name = GetFileNameWithoutExt(g_resource_files.paths[i]),
.type = ResourceGetTypeFromPath(g_resource_files.paths[i]) .type = ResourceGetTypeFromPath(g_resource_files.paths[i])
}; };
// only index resources that the engine knows how to load // only index resources that the engine knows how to load
if(placeholder.type != RESOURCE_MAX) { if(placeholder.type == RESOURCE_SHADER) { // shaders are made up of two files, so their paths are treated differently
// if the shader has already been added, don't accidentally add it twice.
ResourceContainer *found_container = hash_map_get_as(ResourceContainer, &g_resource_map, &placeholder.name);
if(found_container == NULL) {
placeholder.path = GetDirectoryPath(placeholder.path);
LOG_INFO("Internal_IndexResourceDirectory: Indexing %s as %s", placeholder.path, placeholder.name); LOG_INFO("Internal_IndexResourceDirectory: Indexing %s as %s", placeholder.path, placeholder.name);
hash_map_insert(&g_resource_map, &placeholder.name, &placeholder); hash_map_insert(&g_resource_map, &placeholder.name, &placeholder);
LOG_INFO("hash: %zu", strhash(placeholder.name));
}
} else if(placeholder.type != RESOURCE_MAX) { // regular resources
LOG_INFO("Internal_IndexResourceDirectory: Indexing %s as %s", placeholder.path, placeholder.name);
hash_map_insert(&g_resource_map, &placeholder.name, &placeholder);
LOG_INFO("hash: %zu", strhash(placeholder.name));
} }
} }
} }
@ -104,6 +120,7 @@ void InitializeResourceSubsystem() {
void CleanResourceSubsystem() { void CleanResourceSubsystem() {
List resources = hash_map_values(&g_resource_map); List resources = hash_map_values(&g_resource_map);
list_foreach(ResourceContainer *,resource, &resources) list_foreach(ResourceContainer *,resource, &resources)
if(resource->is_loaded)
g_unload_functions[resource->type](resource); g_unload_functions[resource->type](resource);
hash_map_empty(&g_resource_map); hash_map_empty(&g_resource_map);
UnloadDirectoryFiles(g_resource_files); UnloadDirectoryFiles(g_resource_files);
@ -128,7 +145,7 @@ bool GetTextureResource(char const *path, TextureResource *out) {
*out = ResourceEmpty(Texture); *out = ResourceEmpty(Texture);
// assert some assumptions about the found resource // assert some assumptions about the found resource
ASSERT_RETURN(container != NULL, false, "GetTextureResource: Resource %s not in index.", path); ASSERT_RETURN(container != NULL, false, "GetTextureResource: Resource %s not in index.", path);
ASSERT_RETURN(container->type != RESOURCE_TEXTURE, false, "GetTextureResource: Resource %s is not a Texture.", path); ASSERT_RETURN(container->type == RESOURCE_TEXTURE, false, "GetTextureResource: Resource %s is not a Texture.", path);
*out = (TextureResource) { *out = (TextureResource) {
.handle = container, .handle = container,
.resource = &container->texture .resource = &container->texture
@ -136,6 +153,18 @@ bool GetTextureResource(char const *path, TextureResource *out) {
return true; return true;
} }
bool GetShaderResource(char const *path, ShaderResource *out) {
ResourceContainer *container = hash_map_get_as(ResourceContainer, &g_resource_map, &path);
*out = ResourceEmpty(Shader);
ASSERT_RETURN(container != NULL, false, "GetShaderResource: Resource %s not in index.", path);
ASSERT_RETURN(container->type == RESOURCE_SHADER, false, "GetShaderResource: Resource %s is not a Shader.", path);
*out = (ShaderResource) {
.handle = container,
.resource = &container->shader
};
return true;
}
bool IsResourceLoaded(ResourceHandle handle) { bool IsResourceLoaded(ResourceHandle handle) {
return handle->is_loaded; return handle->is_loaded;
} }
@ -157,6 +186,7 @@ void ReleaseResource(ResourceHandle handle) {
static static
void Internal_LoadModelResource(ResourceContainer *resource) { void Internal_LoadModelResource(ResourceContainer *resource) {
LOG_INFO("Loading model from: %s", resource->path);
resource->model = LoadModel(resource->path); resource->model = LoadModel(resource->path);
} }
@ -176,3 +206,16 @@ void Internal_UnloadTextureResource(ResourceContainer *resource) {
UnloadTexture(resource->texture); UnloadTexture(resource->texture);
resource->texture = (Texture){0}; resource->texture = (Texture){0};
} }
static
void Internal_LoadShaderResource(ResourceContainer *resource) {
resource->shader = LoadShader(TextFormat("%s/%s.vs", resource->path, resource->name), TextFormat("%s/%s.fs", resource->path, resource->name));
ASSERT_RETURN(IsShaderReady(resource->shader),, "Internal_LoadShaderResource: Shader failed to load.");
}
static
void Internal_UnloadShaderResource(ResourceContainer *resource) {
UnloadShader(resource->shader);
resource->shader = (Shader){0};
}

View file

@ -11,6 +11,7 @@ typedef struct ResourceContainer* ResourceHandle;
ResourceType(Model); ResourceType(Model);
ResourceType(Texture); ResourceType(Texture);
ResourceType(Shader);
//! Allocate and initialize memory required to operate resource subsystem //! Allocate and initialize memory required to operate resource subsystem
extern void InitializeResourceSubsystem(); extern void InitializeResourceSubsystem();
@ -20,6 +21,8 @@ extern void CleanResourceSubsystem();
extern bool GetModelResource(char const *path, ModelResource *out); extern bool GetModelResource(char const *path, ModelResource *out);
//! Get indexed texture from resources. //! Get indexed texture from resources.
extern bool GetTextureResource(char const *path, TextureResource *out); extern bool GetTextureResource(char const *path, TextureResource *out);
//! Get indexed shader from resources.
extern bool GetShaderResource(char const *path, ShaderResource *out);
//! Check if a resource is loaded or not. //! Check if a resource is loaded or not.
extern bool IsResourceLoaded(ResourceHandle handle); extern bool IsResourceLoaded(ResourceHandle handle);

View file

@ -9,22 +9,30 @@
#include "utils/debug.h" #include "utils/debug.h"
Scene *CreateInitialScene() { Scene *CreateInitialScene() {
Transformable transformable;
Transform transform;
SceneNode *root = CreateTransformNode(); SceneNode *root = CreateTransformNode();
// create a model with a camera attached as a child of the root of the scene
SceneNode *model_parent = CreateTransformNode(); SceneNode *model_parent = CreateTransformNode();
SceneNodeAddChild(root, model_parent); SceneNodeAddChild(root, model_parent);
// create the rest of the scene with a mesh and a functionality node
SceneNode *camera_parent = CreateTransformNode(); SceneNodeAddChild(model_parent, CreateMeshRenderEntity("spacefighter"));
SceneNodeAddChild(model_parent, camera_parent); SceneNodeAddChild(model_parent, CreateTestObject());
// set camera parent location transformable = TC_CAST(model_parent->entity, Transformable);
Transformable transformable = TC_CAST(camera_parent->entity, Transformable); transform = transformable.tc->get_global_transform(transformable.data);
Transform transform = transformable.tc->get_transform(transformable.data); transform.translation.y += 10;
transform.translation = (Vector3){0.f, 3.f, -10.f}; transformable.tc->set_global_transform(transformable.data, transform);
// create a camera attached to it's own transform node
SceneNode *camera_parent = CreateTransformNode(); // the parent
SceneNodeAddChild(model_parent, camera_parent); // attached to the model parent
// set camera parent offset
transformable = TC_CAST(camera_parent->entity, Transformable);
transform = transformable.tc->get_transform(transformable.data);
transform.translation = (Vector3){-3.f, 3.f, -10.f};
transform.rotation = QuaternionFromEuler(7.5f * DEG2RAD, 0.f, 0.f); transform.rotation = QuaternionFromEuler(7.5f * DEG2RAD, 0.f, 0.f);
transformable.tc->set_transform(transformable.data, transform); transformable.tc->set_transform(transformable.data, transform);
// create the camera and attach it to the dedicated transform node
SceneNodeAddChild(camera_parent, CreateCameraNode()); SceneNodeAddChild(camera_parent, CreateCameraNode());
SceneNodeAddChild(model_parent, CreateMeshRenderEntity("spacefighter.glb"));
SceneNodeAddChild(model_parent, CreateTestObject());
return CreateScene(root); return CreateScene(root);
} }

@ -1 +1 @@
Subproject commit c4ec92fa82ab0bbee24f5c60ce36455a37d3696d Subproject commit af50174b71853f3ca887fc0e064e88258c412f2c