models now rendering

This commit is contained in:
matthew 2025-06-18 15:24:40 +10:00
parent 874b5de482
commit 25292c0347
6 changed files with 284 additions and 111 deletions

Binary file not shown.

View File

@ -435,10 +435,6 @@ apParseModel(u8 *data)
{ {
switch (m3d->material[i].prop[j].type) switch (m3d->material[i].prop[j].type)
{ {
case m3dp_Kd:
{
U32ColToVec4(&model->materials.data[i].props.albedo, m3d->material[i].prop[j].value.color);
} break;
case m3dp_Ka: case m3dp_Ka:
{ {
U32ColToVec4(&model->materials.data[i].props.ambient, m3d->material[i].prop[j].value.color); U32ColToVec4(&model->materials.data[i].props.ambient, m3d->material[i].prop[j].value.color);
@ -474,7 +470,7 @@ apParseModel(u8 *data)
} }
u32 num_meshes = 0; u32 num_meshes = 0;
u32 last = UINT32_MAX; u64 last = UINT64_MAX;
for (u64 i = 0; i < m3d->numface; i += 1) for (u64 i = 0; i < m3d->numface; i += 1)
{ {
if (m3d->face[i].materialid != last) if (m3d->face[i].materialid != last)
@ -487,11 +483,11 @@ apParseModel(u8 *data)
model->meshes.length = u64(num_meshes); model->meshes.length = u64(num_meshes);
model->meshes.data = (apMesh *)malloc(sizeof(apMesh) * num_meshes); model->meshes.data = (apMesh *)malloc(sizeof(apMesh) * num_meshes);
last = UINT32_MAX; last = UINT64_MAX;
u32 current_index = 0; u32 current_index = 0;
for (u64 i = 0, j = 0; i < m3d->numface; i += 1, j += 3) for (u64 i = 0, j = 0; i < m3d->numface; i += 1, j += 3)
{ {
if (last == UINT32_MAX) if (last == UINT64_MAX)
{ {
model->meshes.data[current_index].mat_idx = m3d->face[i].materialid; model->meshes.data[current_index].mat_idx = m3d->face[i].materialid;
model->meshes.data[current_index].start_idx = 0; model->meshes.data[current_index].start_idx = 0;
@ -542,6 +538,12 @@ apParseModel(u8 *data)
model->vertices.data[j+2].normal.y = m3d->vertex[m3d->face[i].normal[2]].y; model->vertices.data[j+2].normal.y = m3d->vertex[m3d->face[i].normal[2]].y;
model->vertices.data[j+2].normal.z = m3d->vertex[m3d->face[i].normal[2]].z; model->vertices.data[j+2].normal.z = m3d->vertex[m3d->face[i].normal[2]].z;
model->vertices.data[j+0].color = m3d->vertex[m3d->face[i].vertex[0]].color;
model->vertices.data[j+1].color = m3d->vertex[m3d->face[i].vertex[1]].color;
model->vertices.data[j+2].color = m3d->vertex[m3d->face[i].vertex[2]].color;
if (m3d->numtmap)
{
model->vertices.data[j+0].uv.x = m3d->tmap[m3d->face[i].texcoord[0]].u; model->vertices.data[j+0].uv.x = m3d->tmap[m3d->face[i].texcoord[0]].u;
model->vertices.data[j+0].uv.y = m3d->tmap[m3d->face[i].texcoord[0]].v; model->vertices.data[j+0].uv.y = m3d->tmap[m3d->face[i].texcoord[0]].v;
@ -550,6 +552,7 @@ apParseModel(u8 *data)
model->vertices.data[j+2].uv.x = m3d->tmap[m3d->face[i].texcoord[2]].u; model->vertices.data[j+2].uv.x = m3d->tmap[m3d->face[i].texcoord[2]].u;
model->vertices.data[j+2].uv.y = m3d->tmap[m3d->face[i].texcoord[2]].v; model->vertices.data[j+2].uv.y = m3d->tmap[m3d->face[i].texcoord[2]].v;
}
model->indices.data[j+0] = j+0; model->indices.data[j+0] = j+0;
model->indices.data[j+1] = j+1; model->indices.data[j+1] = j+1;
@ -561,12 +564,6 @@ apParseModel(u8 *data)
#endif #endif
} }
for (u64 i = 0; i < model->meshes.length; i += 1)
{
apMesh *mesh = model->meshes.data + i;
Printfln("mat_idx: %llu start_idx: %llu length: %llu", mesh->mat_idx, mesh->start_idx, mesh->length);
}
model->m3d = m3d; model->m3d = m3d;
return model; return model;

View File

@ -16,6 +16,7 @@ typedef struct apVertex
Vec3 pos; Vec3 pos;
Vec3 normal; Vec3 normal;
Vec2 uv; Vec2 uv;
u32 color;
} apVertex; } apVertex;
ArrayType(apVertex); ArrayType(apVertex);
@ -30,7 +31,6 @@ typedef struct Image
typedef struct apMatProps typedef struct apMatProps
{ {
Vec4 albedo;
Vec4 ambient; Vec4 ambient;
Vec4 specular; Vec4 specular;
f32 shininess; f32 shininess;

View File

@ -18,6 +18,13 @@ Init(Renderer *renderer)
{ {
b32 success = true; b32 success = true;
renderer->perm_arena = ArenaCreate(MB(32));
for (u64 i = 0; i < FRAME_OVERLAP; i += 1)
{
renderer->frame_arenas[i] = ArenaCreate(MB(16));
}
RGFW_setGLHint(RGFW_glMajor, 4); RGFW_setGLHint(RGFW_glMajor, 4);
RGFW_setGLHint(RGFW_glMinor, 6); RGFW_setGLHint(RGFW_glMinor, 6);
RGFW_setGLHint(RGFW_glProfile, RGFW_glCore); RGFW_setGLHint(RGFW_glProfile, RGFW_glCore);
@ -41,20 +48,29 @@ Init(Renderer *renderer)
} }
} }
#ifdef BUILD_DEBUG
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(DebugCallback, NULL);
#endif
for (u32 i = 0; i < PIPELINE_MAX; i += 1) for (u32 i = 0; i < PIPELINE_MAX; i += 1)
{ {
renderer->pipelines[i] = BuildPipeline(g_Pipeline_Create_Info + i); renderer->pipelines[i] = BuildPipeline(g_Pipeline_Create_Info + i);
} }
yoder = rLoadModel("models/yoda"); glCreateBuffers(1, &renderer->mat_buf);
apMatProps props = {0};
glNamedBufferData(renderer->mat_buf, sizeof(apMatProps), &props, GL_STATIC_DRAW);
InitModels(renderer);
return success; return success;
} }
static b32 static void
InitModels(Renderer *renderer) InitModels(Renderer *renderer)
{ {
b32 success = true; Arena *arena = renderer->perm_arena;
for (u64 i = 0; i < MODEL_ASSET_MAX; i += 1) for (u64 i = 0; i < MODEL_ASSET_MAX; i += 1)
{ {
@ -62,9 +78,49 @@ InitModels(Renderer *renderer)
Asset asset = apLoadWithHash(hash); Asset asset = apLoadWithHash(hash);
Assert(asset.model != NULL, "InitModels failure: Model loaded is NULL"); Assert(asset.model != NULL, "InitModels failure: Model loaded is NULL");
apModel *a_model = asset.model;
rModel *model = renderer->models + i;
model->textures.length = a_model->textures.length;
model->textures.data = (u32 *)ArenaAlloc(arena, sizeof(u32) * model->textures.length);
for (u64 j = 0; j < model->textures.length; j += 1)
{
apTexData *t_data = a_model->textures.data + j;
model->textures.data[j] = CreateTexture(t_data->bytes, t_data->w, t_data->h, t_data->ch);
Assert(model->textures.data[j] != GL_NONE, "InitModels failure: texture data is GL_NONE");
} }
return success; apVertexArray v_arr = a_model->vertices;
u32Array i_arr = a_model->indices;
model->buffer = CreateIndexedBuffer(v_arr.data, v_arr.length, i_arr.data, i_arr.length);
// TODO: placeholder/error material
model->meshes.length = a_model->meshes.length;
model->meshes.data = (rMesh *)ArenaAlloc(arena, sizeof(rMesh) * a_model->meshes.length);
for (u64 i = 0; i < model->meshes.length; i += 1)
{
apMesh *a_mesh = a_model->meshes.data + i;
rMesh *mesh = model->meshes.data + i;
mesh->length = a_mesh->length;
mesh->idx_offset = uintptr(a_mesh->start_idx * sizeof(u32));
mesh->type = PPT_NONE;
if (a_mesh->mat_idx != UINT32_MAX)
{
apMaterial *mat = a_model->materials.data + a_mesh->mat_idx;
mesh->type |= mat->tex.albedo != UINT32_MAX ? PPT_ALBEDO_TEX : PPT_ALBEDO_VALUE;
mesh->type |= mat->tex.ambient != UINT32_MAX ? PPT_AMBIENT_TEX : PPT_AMBIENT_VALUE;
mesh->type |= mat->tex.specular != UINT32_MAX ? PPT_SPECULAR_TEX : PPT_SPECULAR_VALUE;
mesh->values = mat->props;
mesh->textures = mat->tex;
}
}
}
} }
static PipelineHandle static PipelineHandle
@ -157,62 +213,38 @@ CreateShader(int type)
return (ShaderHandle)glCreateShader(type); return (ShaderHandle)glCreateShader(type);
} }
static rIndexedBuffer
rLoadModel(char *asset)
{
rIndexedBuffer mesh = {0};
/*
mesh.array = CreateVertexArray();
mesh.vertex = CreateVertexBuffer();
mesh.index = CreateIndexBuffer();
glBindVertexArray(mesh.array);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vertex);
Asset data = apLoad(asset);
Assert(data.model != NULL, "CreateMeshBuffer failed to load asset");
mesh.draw_count = data.model_meta.i_count;
Printfln("v_count: %llu", data.model->v_count);
glBufferData(
GL_ARRAY_BUFFER,
data.model->v_count * sizeof(apVertex),
data.model->vertices,
GL_STATIC_DRAW
);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.index);
glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
data.model->i_count * sizeof(u32),
data.model->indices,
GL_STATIC_DRAW
);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(apVertex), 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(apVertex), (void *)offsetof(apVertex, col));
apUnload(asset);
glBindVertexArray(0);
*/
return mesh;
}
// ::Init::Impl::End:: // ::Init::Impl::End::
// ::Draw::Impl::Start:: // ::Draw::Impl::Start::
static void
rDrawModel(Renderer *renderer, rModel *model)
{
glUseProgram(renderer->pipelines[PIPELINE_PBR]);
for (u64 i = 0; i < model->meshes.length; i += 1)
{
rMesh *mesh = model->meshes.data + i;
u32 albedo = mesh->textures.albedo != UINT32_MAX ? mesh->textures.albedo : 0;
glBindTextureUnit(0, albedo);
u32 ambient = mesh->textures.ambient != UINT32_MAX ? mesh->textures.ambient : 0;
glBindTextureUnit(1, ambient);
u32 specular = mesh->textures.specular != UINT32_MAX ? mesh->textures.ambient : 0;
glBindTextureUnit(2, specular);
glNamedBufferSubData(renderer->mat_buf, 0, sizeof(apMatProps), &mesh->values);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, renderer->mat_buf);
glBindVertexArray(model->buffer.vao);
glDrawElements(GL_TRIANGLES, mesh->length, GL_UNSIGNED_INT, (void *)(model->buffer.ioffset + mesh->idx_offset));
}
}
static void static void
DrawIndexedBuffer(rIndexedBuffer *buffer) DrawIndexedBuffer(rIndexedBuffer *buffer)
{ {
@ -220,7 +252,6 @@ DrawIndexedBuffer(rIndexedBuffer *buffer)
glDrawElements(GL_TRIANGLES, buffer->icount, GL_UNSIGNED_INT, (void *)buffer->ioffset); glDrawElements(GL_TRIANGLES, buffer->icount, GL_UNSIGNED_INT, (void *)buffer->ioffset);
} }
// ::Draw::Impl::End:: // ::Draw::Impl::End::
@ -242,8 +273,8 @@ CreateIndexedBuffer(rawptr vert_data, u32 vcount, rawptr idx_data, u32 icount)
isize idx_len_aligned = Align(idx_len, alignment); isize idx_len_aligned = Align(idx_len, alignment);
#if BUILD_DEBUG #if BUILD_DEBUG
Assert((vert_len_aligned / alignment) == 0, "Buffers are not aligned"); Assert((vert_len_aligned % alignment) == 0, "Buffers are not aligned");
Assert((idx_len_aligned / alignment) == 0, "Buffers are not aligned"); Assert((idx_len_aligned % alignment) == 0, "Buffers are not aligned");
#endif #endif
isize vert_offset = 0; isize vert_offset = 0;
@ -258,19 +289,16 @@ CreateIndexedBuffer(rawptr vert_data, u32 vcount, rawptr idx_data, u32 icount)
glCreateVertexArrays(1, &vao); glCreateVertexArrays(1, &vao);
constexpr u32 pos_size = SizeOfMember(apVertex, pos) / sizeof(f32); constexpr u32 pos_size = SizeOfMember(apVertex, pos) / sizeof(f32);
glEnableVertexArrayAttrib(vao, 0); SetVertexAttrib(vao, 0, pos_size, GL_FLOAT, GL_FALSE, offsetof(apVertex, pos));
glVertexArrayAttribBinding(vao, 0, 0);
glVertexArrayAttribFormat(vao, 0, pos_size, GL_FLOAT, GL_FALSE, 0);
constexpr u32 normal_size = SizeOfMember(apVertex, normal) / sizeof(f32); constexpr u32 normal_size = SizeOfMember(apVertex, normal) / sizeof(f32);
glEnableVertexArrayAttrib(vao, 1); SetVertexAttrib(vao, 1, normal_size, GL_FLOAT, GL_FALSE, offsetof(apVertex, normal));
glVertexArrayAttribBinding(vao, 1, 0);
glVertexArrayAttribFormat(vao, 1, normal_size, GL_FLOAT, GL_FALSE, offsetof(apVertex, normal)); constexpr u32 col_size = SizeOfMember(apVertex, color) / sizeof(u8);
SetVertexAttrib(vao, 2, col_size, GL_UNSIGNED_BYTE, GL_FALSE, offsetof(apVertex, color));
constexpr u32 uv_size = SizeOfMember(apVertex, uv) / sizeof(f32); constexpr u32 uv_size = SizeOfMember(apVertex, uv) / sizeof(f32);
glEnableVertexArrayAttrib(vao, 2); SetVertexAttrib(vao, 3, uv_size, GL_FLOAT, GL_FALSE, offsetof(apVertex, uv));
glVertexArrayAttribBinding(vao, 2, 0);
glVertexArrayAttribFormat(vao, 2, uv_size, GL_FLOAT, GL_FALSE, offsetof(apVertex, uv));
glVertexArrayVertexBuffer(vao, 0, buffer, vert_offset, sizeof(apVertex)); glVertexArrayVertexBuffer(vao, 0, buffer, vert_offset, sizeof(apVertex));
glVertexArrayElementBuffer(vao, buffer); glVertexArrayElementBuffer(vao, buffer);
@ -284,6 +312,14 @@ CreateIndexedBuffer(rawptr vert_data, u32 vcount, rawptr idx_data, u32 icount)
return indexed_buffer; return indexed_buffer;
} }
static void
SetVertexAttrib(u32 vao, u32 idx, u32 count, i32 type, b32 normalized, u32 offset)
{
glEnableVertexArrayAttrib(vao, idx);
glVertexArrayAttribBinding(vao, idx, 0);
glVertexArrayAttribFormat(vao, idx, count, type, normalized, offset);
}
// ::Buffers::Impl::End:: // ::Buffers::Impl::End::
@ -302,20 +338,29 @@ CreateTexture(rawptr data, u32 width, u32 height, u32 channels)
switch (channels) switch (channels)
{ {
case 1: case 1:
{
format = GL_R8; format = GL_R8;
copy_format = GL_RED; copy_format = GL_RED;
break; } break;
case 2: case 2:
{
format = GL_RG8; format = GL_RG8;
copy_format = GL_RG; copy_format = GL_RG;
} break;
case 3: case 3:
{
format = GL_RGB8; format = GL_RGB8;
copy_format = GL_RGB; copy_format = GL_RGB;
} break;
case 4: case 4:
{
format = GL_RGBA8; format = GL_RGBA8;
copy_format = GL_RGBA; copy_format = GL_RGBA;
} break;
default: default:
{
Assert(false, "CreateTexture failure: unsupported channel number passed in"); Assert(false, "CreateTexture failure: unsupported channel number passed in");
} break;
} }
glTextureStorage2D(tex, mipmap, format, width, height); glTextureStorage2D(tex, mipmap, format, width, height);
@ -339,16 +384,121 @@ RunCycle(Renderer *renderer)
{ {
while (RGFW_window_checkEvent(renderer->window)); while (RGFW_window_checkEvent(renderer->window));
Asset yoder = apLoad("models/yoda");
glUseProgram(renderer->pipelines[PIPELINE_PBR]); glUseProgram(renderer->pipelines[PIPELINE_PBR]);
glClearColor(0.1f, 0.8f, 0.4f, 1.0f); glClearColor(0.1f, 0.8f, 0.4f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
//DrawMeshBuffer(&yoder); rDrawModel(renderer, renderer->models + 2);
RGFW_window_swapBuffers(renderer->window); RGFW_window_swapBuffers(renderer->window);
return !RGFW_window_shouldClose(renderer->window); return !RGFW_window_shouldClose(renderer->window);
} }
// ::Debug::Impl::Start::
void DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, GLchar const* message, void const* user_param)
{
if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) return;
const char *source_str, *type_str, *severity_str;
switch (source)
{
case GL_DEBUG_SOURCE_API:
{
source_str = "API";
} break;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
{
source_str = "WINDOW SYSTEM";
} break;
case GL_DEBUG_SOURCE_SHADER_COMPILER:
{
source_str = "SHADER COMPILER";
} break;
case GL_DEBUG_SOURCE_THIRD_PARTY:
{
source_str = "THIRD PARTY";
} break;
case GL_DEBUG_SOURCE_APPLICATION:
{
source_str = "APPLICATION";
} break;
case GL_DEBUG_SOURCE_OTHER:
{
source_str = "OTHER";
} break;
default:
{
source_str = "UNKNOWN";
} break;
}
switch (type)
{
case GL_DEBUG_TYPE_ERROR:
{
type_str = "ERROR";
} break;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
{
type_str = "DEPRECATED BEHAVIOR";
} break;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
{
type_str = "UNDEFINED BEHAVIOR";
} break;
case GL_DEBUG_TYPE_PORTABILITY:
{
type_str = "PORTABILITY";
} break;
case GL_DEBUG_TYPE_PERFORMANCE:
{
type_str = "PERFORMANCE";
} break;
case GL_DEBUG_TYPE_MARKER:
{
type_str = "MARKER";
} break;
case GL_DEBUG_TYPE_OTHER:
{
type_str = "OTHER";
} break;
default:
{
type_str = "UNKNOWN";
} break;
}
switch (severity)
{
case GL_DEBUG_SEVERITY_NOTIFICATION:
{
severity_str = "NOTIFICATION";
} break;
case GL_DEBUG_SEVERITY_LOW:
{
severity_str = "LOW";
} break;
case GL_DEBUG_SEVERITY_MEDIUM:
{
severity_str = "MEDIUM";
} break;
case GL_DEBUG_SEVERITY_HIGH:
{
severity_str = "HIGH";
} break;
default:
{
severity_str = "UNKNOWN";
} break;
}
Printfln("Source: [%s] \nType: [%s] \nSeverity: [%s] \n%s", source_str, type_str, severity_str, message);
}
// ::Debug::Impl::End::

View File

@ -5,6 +5,8 @@
#include "assets.h" #include "assets.h"
constexpr u64 FRAME_OVERLAP = 2;
typedef enum Pipeline_e typedef enum Pipeline_e
{ {
PIPELINE_PBR, PIPELINE_PBR,
@ -12,6 +14,17 @@ typedef enum Pipeline_e
PIPELINE_MAX, PIPELINE_MAX,
} Pipeline; } Pipeline;
typedef enum PBRPropType_e
{
PPT_NONE = 0x0000,
PPT_ALBEDO_VALUE = 0x0001,
PPT_AMBIENT_VALUE = 0x0002,
PPT_SPECULAR_VALUE = 0x0004,
PPT_ALBEDO_TEX = 0x0008,
PPT_AMBIENT_TEX = 0x0010,
PPT_SPECULAR_TEX = 0x0020,
} PBRPropType;
typedef struct PipelineCreateInfo typedef struct PipelineCreateInfo
{ {
char *vertex_shader; char *vertex_shader;
@ -33,29 +46,36 @@ typedef struct rIndexedBuffer
typedef struct rMesh typedef struct rMesh
{ {
rIndexedBuffer buffer; apMatProps values;
apMatProps material; apMatTextures textures;
u32 texture; uintptr idx_offset;
u64 length;
u32 type;
} rMesh; } rMesh;
ArrayType(rMesh); ArrayType(rMesh);
typedef struct rModel typedef struct rModel
{ {
rIndexedBuffer buffer;
rMeshArray meshes; rMeshArray meshes;
u32Array textures;
} rModel; } rModel;
typedef struct Renderer typedef struct Renderer
{ {
RGFW_window *window; RGFW_window *window;
PipelineHandle pipelines[PIPELINE_MAX]; PipelineHandle pipelines[PIPELINE_MAX];
rIndexedBuffer models[MODEL_ASSET_MAX]; rModel models[MODEL_ASSET_MAX];
u32 mat_buf;
Arena *perm_arena;
Arena *frame_arenas[FRAME_OVERLAP];
} Renderer; } Renderer;
// ::Init::Decl:: // ::Init::Decl::
static b32 Init(Renderer *renderer); static b32 Init(Renderer *renderer);
static b32 InitModels(Renderer *renderer); static void InitModels(Renderer *renderer);
static PipelineHandle CreatePipeline(); static PipelineHandle CreatePipeline();
static VertexBuffer CreateVertexBuffer(); static VertexBuffer CreateVertexBuffer();
static IndexBuffer CreateIndexBuffer(); static IndexBuffer CreateIndexBuffer();
@ -68,11 +88,14 @@ static b32 BuildShader(ShaderHandle *handle, char *asset);
// ::Draw::Decl:: // ::Draw::Decl::
static void DrawIndexedBuffer(rIndexedBuffer *buffer); static void DrawIndexedBuffer(rIndexedBuffer *buffer);
static void rDrawModel(Renderer *renderer, rModel *model);
// ::Buffers::Decl:: // ::Buffers::Decl::
static rIndexedBuffer rLoadModel(char *asset); static rIndexedBuffer rLoadModel(char *asset);
static rIndexedBuffer CreateIndexedBuffer(rawptr vert_data, u32 vcount, rawptr idx_data, u32 icount); static rIndexedBuffer CreateIndexedBuffer(rawptr vert_data, u32 vcount, rawptr idx_data, u32 icount);
static void SetVertexAttrib(u32 vao, u32 idx, u32 count, i32 type, b32 normalized, u32 offset);
static u32 rCreateBuffer(rawptr data, u32 size);
// ::Textures::Decl:: // ::Textures::Decl::
@ -82,3 +105,7 @@ static u32 CreateTexture(rawptr data, u32 width, u32 height, u32 channels);
static void DrawMeshBuffer(rIndexedBuffer *mesh); static void DrawMeshBuffer(rIndexedBuffer *mesh);
// ::Debug::Decl::
void DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, GLchar const* message, void const* user_param);

View File

@ -2,14 +2,14 @@
layout (location = 0) in vec3 in_pos; layout (location = 0) in vec3 in_pos;
layout (location = 1) in vec3 in_normal; layout (location = 1) in vec3 in_normal;
layout (location = 2) in vec2 in_uv; layout (location = 2) in vec4 in_color;
layout (location = 3) in vec2 in_uv;
layout (location = 0) out vec4 out_color; layout (location = 0) out vec4 out_color;
layout (location = 1) out vec2 out_uv; layout (location = 1) out vec2 out_uv;
layout (std140, location = 0) uniform Properties layout (std140, binding = 0) uniform Properties
{ {
vec4 color;
vec4 ambient; vec4 ambient;
vec4 diffuse; vec4 diffuse;
vec4 specular; vec4 specular;
@ -19,10 +19,9 @@ layout (std140, location = 0) uniform Properties
layout (binding = 0) uniform sampler2D albedo_texture; layout (binding = 0) uniform sampler2D albedo_texture;
layout (binding = 1) uniform sampler2D ambient_texture; layout (binding = 1) uniform sampler2D ambient_texture;
layout (binding = 2) uniform sampler2D specular_texture; layout (binding = 2) uniform sampler2D specular_texture;
layout (binding = 3) uniform sampler2D emission_texture;
void main() void main()
{ {
gl_Position = vec4(in_pos, 1.0); gl_Position = vec4(in_pos, 1.0);
out_color = in_color; out_color = texture(albedo_texture, in_uv);
} }