adding gfx and ui stuff
This commit is contained in:
275
gfx/render.c
Normal file
275
gfx/render.c
Normal file
@@ -0,0 +1,275 @@
|
||||
#include "render.h"
|
||||
|
||||
static RenderObjects_Char createCharObjects(Arena *arena, size_t count) {
|
||||
RenderObjects_Char result = {0};
|
||||
result.count = count;
|
||||
|
||||
result.begin.buf = PushFullList(arena, Vec2List, count);
|
||||
result.glyph.buf = PushFullList(arena, IntList, count);
|
||||
result.fontSize.buf = PushFullList(arena, FloatList, count);
|
||||
result.color.buf = PushFullList(arena, Vec4List, count);
|
||||
|
||||
glGenVertexArrays(1, &result.vao);
|
||||
|
||||
glGenBuffers(1, &result.begin.bufId);
|
||||
glGenBuffers(1, &result.glyph.bufId);
|
||||
glGenBuffers(1, &result.fontSize.bufId);
|
||||
glGenBuffers(1, &result.color.bufId);
|
||||
|
||||
glBindVertexArray(result.vao);
|
||||
|
||||
int32 bufItemSize = sizeof(result.begin.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.begin.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.begin.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(0, 1);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
bufItemSize = sizeof(result.glyph.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.glyph.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.glyph.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribIPointer(1, 1, GL_INT, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(1, 1);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
bufItemSize = sizeof(result.fontSize.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.fontSize.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.fontSize.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(2, 1);
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
bufItemSize = sizeof(result.color.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.color.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.color.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(3, 1);
|
||||
glEnableVertexAttribArray(3);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static RenderObjects_Rect createRectangleObjects(Arena *arena, size_t count) {
|
||||
RenderObjects_Rect result = {0};
|
||||
result.count = count;
|
||||
|
||||
result.p0.buf = PushFullList(arena, Vec2List, count);
|
||||
result.p1.buf = PushFullList(arena, Vec2List, count);
|
||||
result.color.buf = PushFullList(arena, Vec4List, count);
|
||||
result.borderRadius.buf = PushFullList(arena, FloatList, count);
|
||||
result.borderThickness.buf = PushFullList(arena, FloatList, count);
|
||||
result.borderColor.buf = PushFullList(arena, Vec4List, count);
|
||||
result.edgeSoftness.buf = PushFullList(arena, FloatList, count);
|
||||
|
||||
glGenVertexArrays(1, &result.vao);
|
||||
|
||||
glGenBuffers(1, &result.p0.bufId);
|
||||
glGenBuffers(1, &result.p1.bufId);
|
||||
glGenBuffers(1, &result.color.bufId);
|
||||
glGenBuffers(1, &result.borderRadius.bufId);
|
||||
glGenBuffers(1, &result.borderThickness.bufId);
|
||||
glGenBuffers(1, &result.borderColor.bufId);
|
||||
glGenBuffers(1, &result.edgeSoftness.bufId);
|
||||
|
||||
glBindVertexArray(result.vao);
|
||||
|
||||
int32 bufItemSize = sizeof(result.p0.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.p0.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.p0.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(0, 1);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
bufItemSize = sizeof(result.p1.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.p1.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.p1.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(1, 1);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
bufItemSize = sizeof(result.color.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.color.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.color.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(2, 1);
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
bufItemSize = sizeof(result.borderRadius.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.borderRadius.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.borderRadius.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(3, 1);
|
||||
glEnableVertexAttribArray(3);
|
||||
|
||||
bufItemSize = sizeof(result.borderThickness.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.borderThickness.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.borderThickness.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(4, 1);
|
||||
glEnableVertexAttribArray(4);
|
||||
|
||||
bufItemSize = sizeof(result.borderColor.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.borderColor.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.borderColor.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(5, 1);
|
||||
glEnableVertexAttribArray(5);
|
||||
|
||||
bufItemSize = sizeof(result.edgeSoftness.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.edgeSoftness.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.edgeSoftness.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(6, 1, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(6, 1);
|
||||
glEnableVertexAttribArray(6);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define GL_UpdateBuffer(buffer) \
|
||||
glBindBuffer(GL_ARRAY_BUFFER, (buffer).bufId);\
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, (buffer).buf.length * sizeof((buffer).underlying), (buffer).buf.data);
|
||||
|
||||
static void updateCharObjectBuffers(Renderer *r) {
|
||||
glBindVertexArray(r->chars.vao);
|
||||
GL_UpdateBuffer(r->chars.begin);
|
||||
GL_UpdateBuffer(r->chars.glyph);
|
||||
GL_UpdateBuffer(r->chars.fontSize);
|
||||
GL_UpdateBuffer(r->chars.color);
|
||||
}
|
||||
|
||||
static void updateRectangleObjectBuffers(Renderer *r) {
|
||||
glBindVertexArray(r->rects.vao);
|
||||
GL_UpdateBuffer(r->rects.p0);
|
||||
GL_UpdateBuffer(r->rects.p1);
|
||||
GL_UpdateBuffer(r->rects.color);
|
||||
GL_UpdateBuffer(r->rects.borderRadius);
|
||||
GL_UpdateBuffer(r->rects.borderThickness);
|
||||
GL_UpdateBuffer(r->rects.borderColor);
|
||||
GL_UpdateBuffer(r->rects.edgeSoftness);
|
||||
}
|
||||
|
||||
Renderer createRenderer(Arena *arena, Scene *scene, Camera *cam, int32 light) {
|
||||
return (Renderer){
|
||||
.scene = scene,
|
||||
.light = light,
|
||||
.camera = cam,
|
||||
.rects = createRectangleObjects(arena, 1024),
|
||||
.chars = createCharObjects(arena, 10000),
|
||||
};
|
||||
}
|
||||
|
||||
void renderBegin(Renderer *r) {
|
||||
r->rects.p0.buf.length = 0;
|
||||
r->rects.p1.buf.length = 0;
|
||||
r->rects.color.buf.length = 0;
|
||||
r->rects.borderRadius.buf.length = 0;
|
||||
r->rects.borderThickness.buf.length = 0;
|
||||
r->rects.borderColor.buf.length = 0;
|
||||
r->rects.edgeSoftness.buf.length = 0;
|
||||
|
||||
r->chars.begin.buf.length = 0;
|
||||
r->chars.glyph.buf.length = 0;
|
||||
r->chars.fontSize.buf.length = 0;
|
||||
r->chars.color.buf.length = 0;
|
||||
|
||||
r->sceneWidth = 0;
|
||||
r->sceneHeight = 0;
|
||||
r->sceneX = 0;
|
||||
r->sceneY = 0;
|
||||
}
|
||||
|
||||
#define CHECK() do{ GLenum e=glGetError(); if(e) printf("GL err 0x%x at %s:%d\n",e,__FILE__,__LINE__); }while(0)
|
||||
|
||||
void renderEnd(Renderer *r) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// --- 3D Scene ---
|
||||
|
||||
glViewport(r->sceneX, r->height - r->sceneY - r->sceneHeight, r->sceneWidth, r->sceneHeight);
|
||||
cameraSetAspect(r->camera, r->sceneWidth, r->sceneHeight);
|
||||
|
||||
glUseProgram(r->phongShader->progId);
|
||||
setUniformMat4fv(r->phongShader, "projection", &r->camera->proj);
|
||||
setUniformMat4fv(r->phongShader, "view", &r->camera->view);
|
||||
|
||||
SceneGraphNode *lightGraphNode = getSceneGraphNode(r->scene, r->light);
|
||||
setUniform3fv(r->phongShader, "light_pos", &lightGraphNode->translation);
|
||||
setUniform3fv(r->phongShader, "camera", &r->camera->pos);
|
||||
|
||||
//glBindVertexArray(r->cubeMesh->vao);
|
||||
|
||||
int model_uniform = getUniformLocation(r->phongShader, "model");
|
||||
int solid_color_uniform = getUniformLocation(r->phongShader, "solid_color");
|
||||
for (EachIn(r->scene->entities, i)) {
|
||||
Entity *entity = &r->scene->entities.data[i];
|
||||
if (entity->flags & EntityFlags_Render && entity->flags & EntityFlags_Visible) {
|
||||
setUniform4fvByLoc(solid_color_uniform, &entity->color);
|
||||
setUniformMat4fvByLoc(model_uniform, &getSceneGraphNode(r->scene, entity->graphNodeHandle)->world);
|
||||
glBindTexture(GL_TEXTURE_2D, entity->tex->tex_id);
|
||||
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)entity->mesh->num_indices);
|
||||
entity->flags &= ~EntityFlags_Render;
|
||||
}
|
||||
}
|
||||
|
||||
// --- UI overlay ---
|
||||
glViewport(0, 0, r->width, r->height);
|
||||
glUseProgram(r->solidShader->progId);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
Matrix ortho = MatrixOrtho(0.0, r->width, r->height, 0.0, -1.0, 1.0);
|
||||
|
||||
// - 1. Rects
|
||||
updateRectangleObjectBuffers(r);
|
||||
setUniformMat4fv(r->solidShader, "projection", &ortho);
|
||||
glBindVertexArray(r->rects.vao);
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, r->rects.p0.buf.length);
|
||||
|
||||
// - 2. Text
|
||||
updateCharObjectBuffers(r);
|
||||
glUseProgram(r->textShader->progId);
|
||||
setUniformMat4fv(r->textShader, "projection", &ortho);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, r->activeFont->texId);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, r->activeFont->glyphTableTexId);
|
||||
setUniform1i(r->textShader, "glyph_table", 1);
|
||||
|
||||
glBindVertexArray(r->chars.vao);
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, r->chars.begin.buf.length);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
void rendererPlaceRectangle(Renderer *r, real32 x, real32 y, real32 width, real32 height, Vec4 color, real32 borderRadius, real32 borderThickness, Vec4 borderColor) {
|
||||
x = roundf(x);
|
||||
y = roundf(y);
|
||||
width = roundf(width);
|
||||
height = roundf(height);
|
||||
ListAppend(r->rects.p0.buf, ((Vec2){ x, y }));
|
||||
ListAppend(r->rects.p1.buf, ((Vec2){ x + width, y + height }));
|
||||
ListAppend(r->rects.color.buf, color);
|
||||
ListAppend(r->rects.borderRadius.buf, borderRadius);
|
||||
ListAppend(r->rects.borderThickness.buf, borderThickness);
|
||||
ListAppend(r->rects.borderColor.buf, borderColor);
|
||||
ListAppend(r->rects.edgeSoftness.buf, 0.15f);
|
||||
}
|
||||
|
||||
void rendererPlaceString(Renderer *r, string s, real32 x, real32 y, Vec4 color, real32 fontSize) {
|
||||
real32 ratio = fontSize / r->activeFont->lineHeight;
|
||||
real32 charWidth = ratio * r->activeFont->charWidth;
|
||||
for (int i = 0; i < s.length; i++) {
|
||||
ListAppend(r->chars.begin.buf, ((Vec2){ .x=x + i*charWidth, .y=y }));
|
||||
ListAppend(r->chars.glyph.buf, s.str[i] - 32);
|
||||
ListAppend(r->chars.fontSize.buf, ratio);
|
||||
ListAppend(r->chars.color.buf, (color));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user