feat: implemented default shader
This commit is contained in:
parent
fdc92c8c20
commit
a0be00407f
20
resources/default_shader.fs
Normal file
20
resources/default_shader.fs
Normal 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));
|
||||
}
|
25
resources/default_shader.vs
Normal file
25
resources/default_shader.vs
Normal 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 |
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ typedef struct MeshRenderEntity {
|
|||
SceneNode *node;
|
||||
Transformable transform;
|
||||
ModelResource model;
|
||||
ShaderResource shader;
|
||||
} MeshRenderEntity;
|
||||
|
||||
extern SceneNode *CreateMeshRenderEntity(char const *resource_path);
|
||||
|
|
|
@ -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,6 +120,7 @@ void InitializeResourceSubsystem() {
|
|||
void CleanResourceSubsystem() {
|
||||
List resources = hash_map_values(&g_resource_map);
|
||||
list_foreach(ResourceContainer *,resource, &resources)
|
||||
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};
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
28
src/main.c
28
src/main.c
|
@ -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
|
Loading…
Reference in a new issue