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) {
MeshRenderEntity *self = new(MeshRenderEntity);
GetModelResource(resource_path, &self->model);
GetShaderResource("default_shader", &self->shader);
return CreateSceneNode(MeshRenderEntity_as_SceneNodeEntity(self));
}
@ -36,15 +37,24 @@ void MeshRenderEntityEnterTree(MeshRenderEntity *self) {
SceneNodeEntity parent_entity = self->node->parent->entity;
self->transform = TC_CAST(parent_entity, Transformable);
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));
}
void MeshRenderEntityExitTree(MeshRenderEntity *self) {
ReleaseResource(self->model.handle);
ReleaseResource(self->shader.handle);
RemoveRenderable(MeshRenderEntity_as_Renderable(self));
}
void MeshRenderEntityDraw(MeshRenderEntity *self) {
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;
Transformable transform;
ModelResource model;
ShaderResource shader;
} MeshRenderEntity;
extern SceneNode *CreateMeshRenderEntity(char const *resource_path);

View file

@ -8,7 +8,7 @@
char const *RESOURCE_DIRECTORY = "resources";
typedef enum ResourceType {
RESOURCE_MODEL, RESOURCE_TEXTURE,
RESOURCE_MODEL, RESOURCE_TEXTURE, RESOURCE_SHADER,
RESOURCE_MAX
} ResourceType;
@ -21,6 +21,7 @@ typedef struct ResourceContainer {
union {
Model model;
Texture texture;
Shader shader;
};
} ResourceContainer;
@ -31,9 +32,11 @@ static void Internal_LoadModelResource(ResourceContainer *resource);
static void Internal_UnloadModelResource(ResourceContainer *resource);
static void Internal_LoadTextureResource(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};
UnloadResourceFn g_unload_functions[] = {Internal_UnloadModelResource, Internal_UnloadTextureResource};
LoadResourceFn g_load_functions[] = {Internal_LoadModelResource, Internal_LoadTextureResource, Internal_LoadShaderResource};
UnloadResourceFn g_unload_functions[] = {Internal_UnloadModelResource, Internal_UnloadTextureResource, Internal_UnloadShaderResource};
static HashMap g_resource_map;
static FilePathList g_resource_files;
@ -52,6 +55,9 @@ static ResourceType ResourceGetTypeFromPath(char const *path) {
// Model files
if(IsFileExtension(path, ".glb")) 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;
}
@ -85,13 +91,23 @@ void Internal_IndexResourceDirectory() {
.is_loaded = false,
.use_counter = 0,
.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])
};
// 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);
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,7 +120,8 @@ void InitializeResourceSubsystem() {
void CleanResourceSubsystem() {
List resources = hash_map_values(&g_resource_map);
list_foreach(ResourceContainer *,resource, &resources)
g_unload_functions[resource->type](resource);
if(resource->is_loaded)
g_unload_functions[resource->type](resource);
hash_map_empty(&g_resource_map);
UnloadDirectoryFiles(g_resource_files);
}
@ -128,7 +145,7 @@ bool GetTextureResource(char const *path, TextureResource *out) {
*out = ResourceEmpty(Texture);
// assert some assumptions about the found resource
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) {
.handle = container,
.resource = &container->texture
@ -136,6 +153,18 @@ bool GetTextureResource(char const *path, TextureResource *out) {
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) {
return handle->is_loaded;
}
@ -157,6 +186,7 @@ void ReleaseResource(ResourceHandle handle) {
static
void Internal_LoadModelResource(ResourceContainer *resource) {
LOG_INFO("Loading model from: %s", resource->path);
resource->model = LoadModel(resource->path);
}
@ -176,3 +206,16 @@ void Internal_UnloadTextureResource(ResourceContainer *resource) {
UnloadTexture(resource->texture);
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(Texture);
ResourceType(Shader);
//! Allocate and initialize memory required to operate resource subsystem
extern void InitializeResourceSubsystem();
@ -20,6 +21,8 @@ extern void CleanResourceSubsystem();
extern bool GetModelResource(char const *path, ModelResource *out);
//! Get indexed texture from resources.
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.
extern bool IsResourceLoaded(ResourceHandle handle);

View file

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

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