expand shader slightly, added pbr state variables, some code cleanup
This commit is contained in:
parent
6ad3fa83be
commit
b7a6a4f3d9
@ -205,9 +205,8 @@ apLoadImage(u8 *data, u64 len)
|
|||||||
image.h = -1;
|
image.h = -1;
|
||||||
image.ch = -1;
|
image.ch = -1;
|
||||||
|
|
||||||
int ch = 4;
|
|
||||||
int w, h, has_ch;
|
int w, h, has_ch;
|
||||||
u8 *bytes = stbi_load_from_memory(data, len, &w, &h, &has_ch, ch);
|
u8 *bytes = stbi_load_from_memory(data, len, &w, &h, &has_ch, 0);
|
||||||
if (w <= 0 || h <= 0 || has_ch <= 0)
|
if (w <= 0 || h <= 0 || has_ch <= 0)
|
||||||
{
|
{
|
||||||
Printfln("apLoadImage failure: %s", stbi_failure_reason());
|
Printfln("apLoadImage failure: %s", stbi_failure_reason());
|
||||||
@ -250,6 +249,7 @@ apParseModel(u8 *data)
|
|||||||
m3d_t *m3d = m3d_load(data, NULL, NULL, NULL);
|
m3d_t *m3d = m3d_load(data, NULL, NULL, NULL);
|
||||||
Assert(m3d != NULL, "model returned is NULL");
|
Assert(m3d != NULL, "model returned is NULL");
|
||||||
|
|
||||||
|
/*
|
||||||
Printfln("model: %s", m3d->name);
|
Printfln("model: %s", m3d->name);
|
||||||
Printfln("numcmap: %llu", m3d->numcmap);
|
Printfln("numcmap: %llu", m3d->numcmap);
|
||||||
Printfln("numtmap: %llu", m3d->numtmap);
|
Printfln("numtmap: %llu", m3d->numtmap);
|
||||||
@ -266,6 +266,7 @@ apParseModel(u8 *data)
|
|||||||
Printfln("numaction: %llu", m3d->numaction);
|
Printfln("numaction: %llu", m3d->numaction);
|
||||||
Printfln("numinlined: %llu", m3d->numinlined);
|
Printfln("numinlined: %llu", m3d->numinlined);
|
||||||
Printfln("numextra: %llu", m3d->numextra);
|
Printfln("numextra: %llu", m3d->numextra);
|
||||||
|
*/
|
||||||
|
|
||||||
apModel *model = (apModel *)malloc(sizeof(apModel));
|
apModel *model = (apModel *)malloc(sizeof(apModel));
|
||||||
|
|
||||||
@ -283,8 +284,6 @@ apParseModel(u8 *data)
|
|||||||
|
|
||||||
for (u64 i = 0; i < m3d->numtexture; i += 1)
|
for (u64 i = 0; i < m3d->numtexture; i += 1)
|
||||||
{
|
{
|
||||||
Printfln("texture: %s", m3d->texture[i].name);
|
|
||||||
|
|
||||||
model->textures.data[i].bytes = m3d->texture[i].d;
|
model->textures.data[i].bytes = m3d->texture[i].d;
|
||||||
model->textures.data[i].w = m3d->texture[i].w;
|
model->textures.data[i].w = m3d->texture[i].w;
|
||||||
model->textures.data[i].h = m3d->texture[i].h;
|
model->textures.data[i].h = m3d->texture[i].h;
|
||||||
@ -298,8 +297,6 @@ apParseModel(u8 *data)
|
|||||||
|
|
||||||
for (u64 i = 0; i < m3d->nummaterial; i += 1)
|
for (u64 i = 0; i < m3d->nummaterial; i += 1)
|
||||||
{
|
{
|
||||||
Printfln("material: %llu %s", i, m3d->material[i].name);
|
|
||||||
|
|
||||||
model->materials.data[i].tex.albedo = UINT32_MAX;
|
model->materials.data[i].tex.albedo = UINT32_MAX;
|
||||||
model->materials.data[i].tex.ambient = UINT32_MAX;
|
model->materials.data[i].tex.ambient = UINT32_MAX;
|
||||||
model->materials.data[i].tex.specular = UINT32_MAX;
|
model->materials.data[i].tex.specular = UINT32_MAX;
|
||||||
@ -322,17 +319,14 @@ apParseModel(u8 *data)
|
|||||||
} break;
|
} break;
|
||||||
case m3dp_map_Kd:
|
case m3dp_map_Kd:
|
||||||
{
|
{
|
||||||
Printfln("albedo: %llu", m3d->material[i].prop[j].value.textureid);
|
|
||||||
model->materials.data[i].tex.albedo = m3d->material[i].prop[j].value.textureid;
|
model->materials.data[i].tex.albedo = m3d->material[i].prop[j].value.textureid;
|
||||||
} break;
|
} break;
|
||||||
case m3dp_map_Ka:
|
case m3dp_map_Ka:
|
||||||
{
|
{
|
||||||
Printfln("ambient: %llu", m3d->material[i].prop[j].value.textureid);
|
|
||||||
model->materials.data[i].tex.ambient = m3d->material[i].prop[j].value.textureid;
|
model->materials.data[i].tex.ambient = m3d->material[i].prop[j].value.textureid;
|
||||||
} break;
|
} break;
|
||||||
case m3dp_map_Ks:
|
case m3dp_map_Ks:
|
||||||
{
|
{
|
||||||
Printfln("specular: %llu", m3d->material[i].prop[j].value.textureid);
|
|
||||||
model->materials.data[i].tex.specular = m3d->material[i].prop[j].value.textureid;
|
model->materials.data[i].tex.specular = m3d->material[i].prop[j].value.textureid;
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#include "codegen.h"
|
#include "os.h"
|
||||||
|
|
||||||
#include "os.cpp"
|
#include "os.cpp"
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define STG_IMPLEMENTATION
|
|
||||||
|
|
||||||
#include "os.h"
|
|
||||||
|
|
||||||
779
src/renderer.cpp
779
src/renderer.cpp
@ -2,411 +2,9 @@
|
|||||||
|
|
||||||
#include "assets.cpp"
|
#include "assets.cpp"
|
||||||
|
|
||||||
// ::Globals::
|
|
||||||
|
|
||||||
PipelineCreateInfo g_Pipeline_Create_Info[] = {
|
|
||||||
{ .vertex_shader = "shaders/pbr.vert", .fragment_shader = "shaders/pbr.frag" },
|
|
||||||
//{ .vertex_shader = "shaders/gui.vert", .fragment_shader = "shaders/gui.frag" },
|
|
||||||
};
|
|
||||||
|
|
||||||
// ::Init::Impl::Start::
|
|
||||||
|
|
||||||
rIndexedBuffer yoder;
|
|
||||||
|
|
||||||
static b32
|
|
||||||
Init(Renderer *renderer)
|
|
||||||
{
|
|
||||||
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_glMinor, 6);
|
|
||||||
RGFW_setGLHint(RGFW_glProfile, RGFW_glCore);
|
|
||||||
|
|
||||||
renderer->window = RGFW_createWindow("Video Game", RGFW_RECT(0, 0, 1280, 720), RGFW_windowCenter | RGFW_windowNoResize);
|
|
||||||
if (renderer->window == NULL)
|
|
||||||
{
|
|
||||||
Printfln("Failed to create window");
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
RGFW_window_makeCurrent(renderer->window);
|
|
||||||
|
|
||||||
int glad_version = gladLoaderLoadGL();
|
|
||||||
if (!glad_version)
|
|
||||||
{
|
|
||||||
Printfln("gladLoaderLoadGL failure");
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef BUILD_DEBUG
|
|
||||||
glEnable(GL_DEBUG_OUTPUT);
|
|
||||||
glDebugMessageCallback(DebugCallback, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (u32 i = 0; i < PIPELINE_MAX; i += 1)
|
|
||||||
{
|
|
||||||
renderer->pipelines[i] = BuildPipeline(g_Pipeline_Create_Info + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
glCreateBuffers(1, &renderer->mat_buf);
|
|
||||||
apMatProps props = {0};
|
|
||||||
glNamedBufferData(renderer->mat_buf, sizeof(apMatProps), &props, GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
InitModels(renderer);
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
InitModels(Renderer *renderer)
|
|
||||||
{
|
|
||||||
Arena *arena = renderer->perm_arena;
|
|
||||||
|
|
||||||
for (u64 i = 0; i < MODEL_ASSET_MAX; i += 1)
|
|
||||||
{
|
|
||||||
u64 hash = g_Model_Asset_Hashes[i];
|
|
||||||
Asset asset = apLoadWithHash(hash);
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
Printfln("mesh: %llu mat_idx: %llu", i, a_mesh->mat_idx);
|
|
||||||
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.albedo = mat->tex.albedo != UINT32_MAX ? model->textures.data[mat->tex.albedo] : 0;
|
|
||||||
mesh->textures.ambient = mat->tex.ambient != UINT32_MAX ? model->textures.data[mat->tex.ambient] : 0;
|
|
||||||
mesh->textures.specular = mat->tex.specular != UINT32_MAX ? model->textures.data[mat->tex.specular] : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static PipelineHandle
|
|
||||||
BuildPipeline(PipelineCreateInfo *create_info)
|
|
||||||
{
|
|
||||||
auto vertex_shader = CreateShader(GL_VERTEX_SHADER);
|
|
||||||
Assert(BuildShader(&vertex_shader, create_info->vertex_shader), "BuildShader vertex failure");
|
|
||||||
|
|
||||||
auto fragment_shader = CreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
Assert(BuildShader(&fragment_shader, create_info->fragment_shader), "BuildShader fragment failure");
|
|
||||||
|
|
||||||
auto pipeline = CreatePipeline();
|
|
||||||
glAttachShader(pipeline, vertex_shader);
|
|
||||||
glAttachShader(pipeline, fragment_shader);
|
|
||||||
glLinkProgram(pipeline);
|
|
||||||
|
|
||||||
int success = 0;
|
|
||||||
glGetProgramiv(pipeline, GL_LINK_STATUS, &success);
|
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
char info_log[512];
|
|
||||||
glGetProgramInfoLog(pipeline, 512, NULL, info_log);
|
|
||||||
Assert(false, "Failed to build pipeline");
|
|
||||||
}
|
|
||||||
|
|
||||||
return pipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b32
|
|
||||||
BuildShader(ShaderHandle *handle, char *asset)
|
|
||||||
{
|
|
||||||
b32 success = true;
|
|
||||||
|
|
||||||
Asset data = apLoad(asset);
|
|
||||||
Assert(data.bytes != NULL && asset, "Shader data is NULL");
|
|
||||||
|
|
||||||
glShaderBinary(1, handle, GL_SHADER_BINARY_FORMAT_SPIR_V, data.bytes, data.len);
|
|
||||||
glSpecializeShader(*handle, "main", 0, 0, 0);
|
|
||||||
|
|
||||||
int compiled = 0;
|
|
||||||
glGetShaderiv(*handle, GL_COMPILE_STATUS, &compiled);
|
|
||||||
if (!compiled)
|
|
||||||
{
|
|
||||||
char info_log[512];
|
|
||||||
glGetShaderInfoLog(*handle, 512, NULL, info_log);
|
|
||||||
Printfln("Unable to compile shader: %s", info_log);
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PipelineHandle
|
|
||||||
CreatePipeline()
|
|
||||||
{
|
|
||||||
PipelineHandle pipeline = glCreateProgram();
|
|
||||||
return pipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VertexBuffer
|
|
||||||
CreateVertexBuffer()
|
|
||||||
{
|
|
||||||
VertexBuffer buf;
|
|
||||||
glGenBuffers(1, &buf);
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static IndexBuffer
|
|
||||||
CreateIndexBuffer()
|
|
||||||
{
|
|
||||||
IndexBuffer buf;
|
|
||||||
glGenBuffers(1, &buf);
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VertexArray
|
|
||||||
CreateVertexArray()
|
|
||||||
{
|
|
||||||
VertexArray array;
|
|
||||||
glGenVertexArrays(1, &array);
|
|
||||||
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ShaderHandle
|
|
||||||
CreateShader(int type)
|
|
||||||
{
|
|
||||||
return (ShaderHandle)glCreateShader(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ::Init::Impl::End::
|
|
||||||
|
|
||||||
|
|
||||||
// ::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
|
|
||||||
DrawIndexedBuffer(rIndexedBuffer *buffer)
|
|
||||||
{
|
|
||||||
glBindVertexArray(buffer->vao);
|
|
||||||
glDrawElements(GL_TRIANGLES, buffer->icount, GL_UNSIGNED_INT, (void *)buffer->ioffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ::Draw::Impl::End::
|
|
||||||
|
|
||||||
|
|
||||||
// ::Buffers::Impl::Start::
|
|
||||||
|
|
||||||
static rIndexedBuffer
|
|
||||||
CreateIndexedBuffer(rawptr vert_data, u32 vcount, rawptr idx_data, u32 icount)
|
|
||||||
{
|
|
||||||
i32 alignment = GL_NONE;
|
|
||||||
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment);
|
|
||||||
|
|
||||||
u32 vao = GL_NONE;
|
|
||||||
u32 buffer = GL_NONE;
|
|
||||||
|
|
||||||
isize vert_len = isize(vcount * sizeof(apVertex));
|
|
||||||
isize idx_len = isize(icount * sizeof(u32));
|
|
||||||
|
|
||||||
isize vert_len_aligned = Align(vert_len, alignment);
|
|
||||||
isize idx_len_aligned = Align(idx_len, alignment);
|
|
||||||
|
|
||||||
#if BUILD_DEBUG
|
|
||||||
Assert((vert_len_aligned % alignment) == 0, "Buffers are not aligned");
|
|
||||||
Assert((idx_len_aligned % alignment) == 0, "Buffers are not aligned");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
isize vert_offset = 0;
|
|
||||||
isize idx_offset = vert_len_aligned;
|
|
||||||
|
|
||||||
glCreateBuffers(1, &buffer);
|
|
||||||
glNamedBufferStorage(buffer, idx_len_aligned + vert_len_aligned, NULL, GL_DYNAMIC_STORAGE_BIT);
|
|
||||||
|
|
||||||
glNamedBufferSubData(buffer, vert_offset, vert_len, vert_data);
|
|
||||||
glNamedBufferSubData(buffer, idx_offset, idx_len, idx_data);
|
|
||||||
|
|
||||||
glCreateVertexArrays(1, &vao);
|
|
||||||
|
|
||||||
constexpr u32 pos_size = SizeOfMember(apVertex, pos) / sizeof(f32);
|
|
||||||
SetVertexAttrib(vao, 0, pos_size, GL_FLOAT, GL_FALSE, offsetof(apVertex, pos));
|
|
||||||
|
|
||||||
constexpr u32 normal_size = SizeOfMember(apVertex, normal) / sizeof(f32);
|
|
||||||
SetVertexAttrib(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);
|
|
||||||
SetVertexAttrib(vao, 3, uv_size, GL_FLOAT, GL_FALSE, offsetof(apVertex, uv));
|
|
||||||
|
|
||||||
glVertexArrayVertexBuffer(vao, 0, buffer, vert_offset, sizeof(apVertex));
|
|
||||||
glVertexArrayElementBuffer(vao, buffer);
|
|
||||||
|
|
||||||
rIndexedBuffer indexed_buffer = {0};
|
|
||||||
indexed_buffer.ioffset = idx_offset;
|
|
||||||
indexed_buffer.icount = icount;
|
|
||||||
indexed_buffer.vao = vao;
|
|
||||||
indexed_buffer.buffer = 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::
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ::Textures::Impl::Start::
|
|
||||||
|
|
||||||
static u32
|
|
||||||
CreateTexture(rawptr data, u32 width, u32 height, u32 channels)
|
|
||||||
{
|
|
||||||
u32 tex;
|
|
||||||
glCreateTextures(GL_TEXTURE_2D, 1, &tex);
|
|
||||||
|
|
||||||
i32 mipmap = Mini32(5, i32(log2f(f32(Maxi32(width, height)))));
|
|
||||||
|
|
||||||
u32 format, copy_format;
|
|
||||||
switch (channels)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
format = GL_R8;
|
|
||||||
copy_format = GL_RED;
|
|
||||||
} break;
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
format = GL_RG8;
|
|
||||||
copy_format = GL_RG;
|
|
||||||
} break;
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
format = GL_RGB8;
|
|
||||||
copy_format = GL_RGB;
|
|
||||||
} break;
|
|
||||||
case 4:
|
|
||||||
{
|
|
||||||
format = GL_RGBA8;
|
|
||||||
copy_format = GL_RGBA;
|
|
||||||
} break;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
Assert(false, "CreateTexture failure: unsupported channel number passed in");
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
glTextureStorage2D(tex, mipmap, format, width, height);
|
|
||||||
glTextureSubImage2D(tex, 0, 0, 0, width, height, copy_format, GL_UNSIGNED_BYTE, data);
|
|
||||||
|
|
||||||
glTextureParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
||||||
glTextureParameteri(tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTextureParameterf(tex, GL_TEXTURE_BASE_LEVEL, 0);
|
|
||||||
glTextureParameteri(tex, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
||||||
glTextureParameteri(tex, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
|
|
||||||
glGenerateTextureMipmap(tex);
|
|
||||||
|
|
||||||
return tex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ::Textures::Impl::End::
|
|
||||||
|
|
||||||
static b32
|
|
||||||
RunCycle(Renderer *renderer)
|
|
||||||
{
|
|
||||||
while (RGFW_window_checkEvent(renderer->window));
|
|
||||||
|
|
||||||
glUseProgram(renderer->pipelines[PIPELINE_PBR]);
|
|
||||||
|
|
||||||
glClearColor(0.1f, 0.8f, 0.4f, 1.0f);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
|
|
||||||
rDrawModel(renderer, renderer->models + 2);
|
|
||||||
|
|
||||||
RGFW_window_swapBuffers(renderer->window);
|
|
||||||
|
|
||||||
return !RGFW_window_shouldClose(renderer->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ::Debug::Impl::Start::
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, GLchar const* message, void const* user_param)
|
DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, GLchar const* message, void const* user_param)
|
||||||
{
|
{
|
||||||
return;
|
|
||||||
if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) return;
|
if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) return;
|
||||||
|
|
||||||
const char *source_str, *type_str, *severity_str;
|
const char *source_str, *type_str, *severity_str;
|
||||||
@ -506,4 +104,379 @@ DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei le
|
|||||||
Printfln("Source: [%s] \nType: [%s] \nSeverity: [%s] \n%s", source_str, type_str, severity_str, message);
|
Printfln("Source: [%s] \nType: [%s] \nSeverity: [%s] \n%s", source_str, type_str, severity_str, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ::Debug::Impl::End::
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static rIndexedBuffer
|
||||||
|
CreateIndexedBuffer(rawptr vert_data, u32 vcount, rawptr idx_data, u32 icount)
|
||||||
|
{
|
||||||
|
i32 alignment = GL_NONE;
|
||||||
|
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment);
|
||||||
|
|
||||||
|
u32 vao = GL_NONE;
|
||||||
|
u32 buffer = GL_NONE;
|
||||||
|
|
||||||
|
isize vert_len = isize(vcount * sizeof(apVertex));
|
||||||
|
isize idx_len = isize(icount * sizeof(u32));
|
||||||
|
|
||||||
|
isize vert_len_aligned = Align(vert_len, alignment);
|
||||||
|
isize idx_len_aligned = Align(idx_len, alignment);
|
||||||
|
|
||||||
|
#if BUILD_DEBUG
|
||||||
|
Assert((vert_len_aligned % alignment) == 0, "Buffers are not aligned");
|
||||||
|
Assert((idx_len_aligned % alignment) == 0, "Buffers are not aligned");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
isize vert_offset = 0;
|
||||||
|
isize idx_offset = vert_len_aligned;
|
||||||
|
|
||||||
|
glCreateBuffers(1, &buffer);
|
||||||
|
glNamedBufferStorage(buffer, idx_len_aligned + vert_len_aligned, NULL, GL_DYNAMIC_STORAGE_BIT);
|
||||||
|
|
||||||
|
glNamedBufferSubData(buffer, vert_offset, vert_len, vert_data);
|
||||||
|
glNamedBufferSubData(buffer, idx_offset, idx_len, idx_data);
|
||||||
|
|
||||||
|
glCreateVertexArrays(1, &vao);
|
||||||
|
|
||||||
|
constexpr u32 pos_size = SizeOfMember(apVertex, pos) / sizeof(f32);
|
||||||
|
SetVertexAttrib(vao, 0, pos_size, GL_FLOAT, GL_FALSE, offsetof(apVertex, pos));
|
||||||
|
|
||||||
|
constexpr u32 normal_size = SizeOfMember(apVertex, normal) / sizeof(f32);
|
||||||
|
SetVertexAttrib(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);
|
||||||
|
SetVertexAttrib(vao, 3, uv_size, GL_FLOAT, GL_FALSE, offsetof(apVertex, uv));
|
||||||
|
|
||||||
|
glVertexArrayVertexBuffer(vao, 0, buffer, vert_offset, sizeof(apVertex));
|
||||||
|
glVertexArrayElementBuffer(vao, buffer);
|
||||||
|
|
||||||
|
rIndexedBuffer indexed_buffer = {0};
|
||||||
|
indexed_buffer.ioffset = idx_offset;
|
||||||
|
indexed_buffer.icount = icount;
|
||||||
|
indexed_buffer.vao = vao;
|
||||||
|
indexed_buffer.buffer = buffer;
|
||||||
|
|
||||||
|
return indexed_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32
|
||||||
|
BuildShader(GLuint *handle, char *asset)
|
||||||
|
{
|
||||||
|
b32 success = true;
|
||||||
|
|
||||||
|
Asset data = apLoad(asset);
|
||||||
|
Assert(data.bytes != NULL && asset, "Shader data is NULL");
|
||||||
|
|
||||||
|
glShaderBinary(1, handle, GL_SHADER_BINARY_FORMAT_SPIR_V, data.bytes, data.len);
|
||||||
|
glSpecializeShader(*handle, "main", 0, 0, 0);
|
||||||
|
|
||||||
|
int compiled = 0;
|
||||||
|
glGetShaderiv(*handle, GL_COMPILE_STATUS, &compiled);
|
||||||
|
if (!compiled)
|
||||||
|
{
|
||||||
|
char info_log[512];
|
||||||
|
glGetShaderInfoLog(*handle, 512, NULL, info_log);
|
||||||
|
Printfln("Unable to compile shader: %s", info_log);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32
|
||||||
|
CreateTexture(rawptr data, u32 width, u32 height, u32 channels)
|
||||||
|
{
|
||||||
|
u32 tex;
|
||||||
|
glCreateTextures(GL_TEXTURE_2D, 1, &tex);
|
||||||
|
|
||||||
|
i32 mipmap = Mini32(5, i32(log2f(f32(Maxi32(width, height)))));
|
||||||
|
|
||||||
|
u32 format, copy_format;
|
||||||
|
switch (channels)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
format = GL_R8;
|
||||||
|
copy_format = GL_RED;
|
||||||
|
} break;
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
format = GL_RG8;
|
||||||
|
copy_format = GL_RG;
|
||||||
|
} break;
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
format = GL_RGB8;
|
||||||
|
copy_format = GL_RGB;
|
||||||
|
} break;
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
format = GL_RGBA8;
|
||||||
|
copy_format = GL_RGBA;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Assert(false, "CreateTexture failure: unsupported channel number passed in");
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glTextureStorage2D(tex, mipmap, format, width, height);
|
||||||
|
glTextureSubImage2D(tex, 0, 0, 0, width, height, copy_format, GL_UNSIGNED_BYTE, data);
|
||||||
|
|
||||||
|
glTextureParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
glTextureParameteri(tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTextureParameterf(tex, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
|
glTextureParameteri(tex, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTextureParameteri(tex, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
|
||||||
|
glGenerateTextureMipmap(tex);
|
||||||
|
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
InitModels(Renderer *renderer)
|
||||||
|
{
|
||||||
|
Arena *arena = renderer->perm_arena;
|
||||||
|
|
||||||
|
for (u64 i = 0; i < MODEL_ASSET_MAX; i += 1)
|
||||||
|
{
|
||||||
|
// Init/Load Model
|
||||||
|
u64 hash = g_Model_Asset_Hashes[i];
|
||||||
|
Asset asset = apLoadWithHash(hash);
|
||||||
|
Assert(asset.model != NULL, "InitModels failure: Model loaded is NULL");
|
||||||
|
|
||||||
|
apModel *a_model = asset.model;
|
||||||
|
rModel *model = renderer->models + i;
|
||||||
|
|
||||||
|
// Textures
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertex/Index Buffers
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Material Meshes
|
||||||
|
// TODO: placeholder/error material
|
||||||
|
|
||||||
|
struct StateIndex {
|
||||||
|
rPBRState state;
|
||||||
|
u32 buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
StateIndex *prev_state = (StateIndex *)ArenaAlloc(arena, sizeof(StateIndex) * a_model->meshes.length);
|
||||||
|
u32 state_length = 0;
|
||||||
|
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 = {
|
||||||
|
.idx_offset = uintptr(a_mesh->start_idx * sizeof(u32)),
|
||||||
|
.length = a_mesh->length,
|
||||||
|
};
|
||||||
|
|
||||||
|
rPBRState state;
|
||||||
|
if (a_mesh->mat_idx != INVALID_INDEX)
|
||||||
|
{
|
||||||
|
apMaterial *mat = a_model->materials.data + a_mesh->mat_idx;
|
||||||
|
|
||||||
|
state = {
|
||||||
|
.albedo_tex = mat->tex.albedo != INVALID_INDEX,
|
||||||
|
.ambient_tex = mat->tex.ambient != INVALID_INDEX,
|
||||||
|
.specular_tex = mat->tex.specular != INVALID_INDEX,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (state.albedo_tex)
|
||||||
|
state.channels = a_model->textures.data[mat->tex.albedo].ch;
|
||||||
|
|
||||||
|
u32 state_buffer = INVALID_INDEX;
|
||||||
|
for (u32 i = 0; i < state_length; i += 1)
|
||||||
|
{
|
||||||
|
if (state.albedo_tex != prev_state[i].state.albedo_tex) continue;
|
||||||
|
if (state.ambient_tex != prev_state[i].state.ambient_tex) continue;
|
||||||
|
if (state.specular_tex != prev_state[i].state.specular_tex) continue;
|
||||||
|
if (state.channels != prev_state[i].state.channels) continue;
|
||||||
|
|
||||||
|
state_buffer = prev_state[i].buffer;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state_buffer == INVALID_INDEX)
|
||||||
|
{
|
||||||
|
glCreateBuffers(1, &state_buffer);
|
||||||
|
glNamedBufferStorage(state_buffer, sizeof(rPBRState), &state, GL_DYNAMIC_STORAGE_BIT);
|
||||||
|
prev_state[state_length].state = state;
|
||||||
|
prev_state[state_length].buffer = state_buffer;
|
||||||
|
state_length += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh->state_buffer = state_buffer;
|
||||||
|
|
||||||
|
glCreateBuffers(1, &mesh->mat_buffer);
|
||||||
|
glNamedBufferStorage(mesh->mat_buffer, sizeof(apMatProps), &mat->props, GL_DYNAMIC_STORAGE_BIT);
|
||||||
|
mesh->textures.albedo = mat->tex.albedo != UINT32_MAX ? model->textures.data[mat->tex.albedo] : 0;
|
||||||
|
mesh->textures.ambient = mat->tex.ambient != UINT32_MAX ? model->textures.data[mat->tex.ambient] : 0;
|
||||||
|
mesh->textures.specular = mat->tex.specular != UINT32_MAX ? model->textures.data[mat->tex.specular] : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apUnloadWithHash(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLuint
|
||||||
|
BuildPipeline(PipelineCreateInfo *create_info)
|
||||||
|
{
|
||||||
|
auto vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
Assert(BuildShader(&vertex_shader, create_info->vertex_shader), "BuildShader vertex failure");
|
||||||
|
|
||||||
|
auto fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
Assert(BuildShader(&fragment_shader, create_info->fragment_shader), "BuildShader fragment failure");
|
||||||
|
|
||||||
|
auto pipeline = glCreateProgram();
|
||||||
|
glAttachShader(pipeline, vertex_shader);
|
||||||
|
glAttachShader(pipeline, fragment_shader);
|
||||||
|
glLinkProgram(pipeline);
|
||||||
|
|
||||||
|
int success = 0;
|
||||||
|
glGetProgramiv(pipeline, GL_LINK_STATUS, &success);
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
char info_log[512];
|
||||||
|
glGetProgramInfoLog(pipeline, 512, NULL, info_log);
|
||||||
|
Assert(false, "Failed to build pipeline");
|
||||||
|
}
|
||||||
|
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32
|
||||||
|
Init(Renderer *renderer)
|
||||||
|
{
|
||||||
|
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_glMinor, 6);
|
||||||
|
RGFW_setGLHint(RGFW_glProfile, RGFW_glCore);
|
||||||
|
|
||||||
|
renderer->window = RGFW_createWindow("Video Game", RGFW_RECT(0, 0, 1280, 720), RGFW_windowCenter | RGFW_windowNoResize);
|
||||||
|
if (renderer->window == NULL)
|
||||||
|
{
|
||||||
|
Printfln("Failed to create window");
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
RGFW_window_makeCurrent(renderer->window);
|
||||||
|
|
||||||
|
int glad_version = gladLoaderLoadGL();
|
||||||
|
if (!glad_version)
|
||||||
|
{
|
||||||
|
Printfln("gladLoaderLoadGL failure");
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef BUILD_DEBUG
|
||||||
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
|
glDebugMessageCallback(DebugCallback, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (u32 i = 0; i < PIPELINE_MAX; i += 1)
|
||||||
|
{
|
||||||
|
renderer->pipelines[i] = BuildPipeline(g_Pipeline_Create_Info + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
glCreateBuffers(1, &renderer->mat_buf);
|
||||||
|
apMatProps props = {0};
|
||||||
|
glNamedBufferData(renderer->mat_buf, sizeof(apMatProps), &props, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
InitModels(renderer);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ::Init::Impl::End::
|
||||||
|
|
||||||
|
|
||||||
|
// ::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);
|
||||||
|
|
||||||
|
glBindBufferBase(GL_UNIFORM_BUFFER, 0, mesh->mat_buffer);
|
||||||
|
glBindBufferBase(GL_UNIFORM_BUFFER, 1, mesh->state_buffer);
|
||||||
|
|
||||||
|
glBindVertexArray(model->buffer.vao);
|
||||||
|
glDrawElements(GL_TRIANGLES, mesh->length, GL_UNSIGNED_INT, (void *)(model->buffer.ioffset + mesh->idx_offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
DrawIndexedBuffer(rIndexedBuffer *buffer)
|
||||||
|
{
|
||||||
|
glBindVertexArray(buffer->vao);
|
||||||
|
glDrawElements(GL_TRIANGLES, buffer->icount, GL_UNSIGNED_INT, (void *)buffer->ioffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32
|
||||||
|
RunCycle(Renderer *renderer)
|
||||||
|
{
|
||||||
|
while (RGFW_window_checkEvent(renderer->window));
|
||||||
|
|
||||||
|
glUseProgram(renderer->pipelines[PIPELINE_PBR]);
|
||||||
|
|
||||||
|
glClearColor(0.1f, 0.8f, 0.4f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
rDrawModel(renderer, renderer->models + 2);
|
||||||
|
|
||||||
|
RGFW_window_swapBuffers(renderer->window);
|
||||||
|
|
||||||
|
return !RGFW_window_shouldClose(renderer->window);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include "assets.h"
|
#include "assets.h"
|
||||||
|
|
||||||
constexpr u64 FRAME_OVERLAP = 2;
|
constexpr u64 FRAME_OVERLAP = 2;
|
||||||
|
constexpr u32 INVALID_INDEX = UINT32_MAX;
|
||||||
|
|
||||||
typedef enum Pipeline_e
|
typedef enum Pipeline_e
|
||||||
{
|
{
|
||||||
@ -31,25 +32,27 @@ typedef struct PipelineCreateInfo
|
|||||||
char *fragment_shader;
|
char *fragment_shader;
|
||||||
} PipelineCreateInfo;
|
} PipelineCreateInfo;
|
||||||
|
|
||||||
typedef unsigned int VertexBuffer;
|
|
||||||
typedef unsigned int IndexBuffer;
|
|
||||||
typedef unsigned int PipelineHandle;
|
|
||||||
typedef unsigned int ShaderHandle;
|
|
||||||
typedef unsigned int VertexArray;
|
|
||||||
typedef unsigned int UBO;
|
|
||||||
|
|
||||||
typedef struct rIndexedBuffer
|
typedef struct rIndexedBuffer
|
||||||
{
|
{
|
||||||
i64 icount, ioffset;
|
i64 icount, ioffset;
|
||||||
u32 vao, buffer;
|
u32 vao, buffer;
|
||||||
} rIndexedBuffer;
|
} rIndexedBuffer;
|
||||||
|
|
||||||
|
typedef struct rPBRState
|
||||||
|
{
|
||||||
|
u32 channels;
|
||||||
|
b32 albedo_tex;
|
||||||
|
b32 ambient_tex;
|
||||||
|
b32 specular_tex;
|
||||||
|
} rPBRState;
|
||||||
|
|
||||||
typedef struct rMesh
|
typedef struct rMesh
|
||||||
{
|
{
|
||||||
apMatProps values;
|
|
||||||
apMatTextures textures;
|
apMatTextures textures;
|
||||||
uintptr idx_offset;
|
uintptr idx_offset;
|
||||||
u64 length;
|
u64 length;
|
||||||
|
u32 mat_buffer;
|
||||||
|
u32 state_buffer;
|
||||||
u32 type;
|
u32 type;
|
||||||
} rMesh;
|
} rMesh;
|
||||||
|
|
||||||
@ -65,47 +68,14 @@ typedef struct rModel
|
|||||||
typedef struct Renderer
|
typedef struct Renderer
|
||||||
{
|
{
|
||||||
RGFW_window *window;
|
RGFW_window *window;
|
||||||
PipelineHandle pipelines[PIPELINE_MAX];
|
GLuint pipelines[PIPELINE_MAX];
|
||||||
rModel models[MODEL_ASSET_MAX];
|
rModel models[MODEL_ASSET_MAX];
|
||||||
u32 mat_buf;
|
GLuint mat_buf;
|
||||||
Arena *perm_arena;
|
Arena *perm_arena;
|
||||||
Arena *frame_arenas[FRAME_OVERLAP];
|
Arena *frame_arenas[FRAME_OVERLAP];
|
||||||
} Renderer;
|
} Renderer;
|
||||||
|
|
||||||
// ::Init::Decl::
|
PipelineCreateInfo g_Pipeline_Create_Info[] = {
|
||||||
|
{ .vertex_shader = "shaders/pbr.vert", .fragment_shader = "shaders/pbr.frag" },
|
||||||
static b32 Init(Renderer *renderer);
|
//{ .vertex_shader = "shaders/gui.vert", .fragment_shader = "shaders/gui.frag" },
|
||||||
static void InitModels(Renderer *renderer);
|
};
|
||||||
static PipelineHandle CreatePipeline();
|
|
||||||
static VertexBuffer CreateVertexBuffer();
|
|
||||||
static IndexBuffer CreateIndexBuffer();
|
|
||||||
static VertexArray CreateVertexArray();
|
|
||||||
static ShaderHandle CreateShader(int type);
|
|
||||||
static PipelineHandle BuildPipeline(PipelineCreateInfo *create_info);
|
|
||||||
static UBO CreateUBO(rawptr data, u32 size);
|
|
||||||
static b32 BuildShader(ShaderHandle *handle, char *asset);
|
|
||||||
|
|
||||||
// ::Draw::Decl::
|
|
||||||
|
|
||||||
static void DrawIndexedBuffer(rIndexedBuffer *buffer);
|
|
||||||
static void rDrawModel(Renderer *renderer, rModel *model);
|
|
||||||
|
|
||||||
// ::Buffers::Decl::
|
|
||||||
|
|
||||||
static rIndexedBuffer rLoadModel(char *asset);
|
|
||||||
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::
|
|
||||||
|
|
||||||
static u32 CreateTexture(rawptr data, u32 width, u32 height, u32 channels);
|
|
||||||
|
|
||||||
// ::Draw::Decl::
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,15 @@ layout (std140, binding = 0) uniform Properties
|
|||||||
vec4 diffuse;
|
vec4 diffuse;
|
||||||
vec4 specular;
|
vec4 specular;
|
||||||
float shininess;
|
float shininess;
|
||||||
};
|
} Props;
|
||||||
|
|
||||||
|
layout (std140, binding = 1) uniform PBRState
|
||||||
|
{
|
||||||
|
uint channels;
|
||||||
|
bool albedo_tex;
|
||||||
|
bool ambient_tex;
|
||||||
|
bool specular_tex;
|
||||||
|
} State;
|
||||||
|
|
||||||
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;
|
||||||
@ -22,6 +30,14 @@ layout (binding = 2) uniform sampler2D specular_texture;
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
vec4 col = in_color;
|
||||||
|
|
||||||
|
if (State.albedo_tex)
|
||||||
|
col = texture(albedo_texture, in_uv);
|
||||||
|
|
||||||
|
if (State.channels == 1)
|
||||||
|
col.rgb = col.rrr;
|
||||||
|
|
||||||
gl_Position = vec4(in_pos, 1.0);
|
gl_Position = vec4(in_pos, 1.0);
|
||||||
out_color = texture(albedo_texture, in_uv);
|
out_color = col;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user