Compare commits

...

2 Commits

Author SHA1 Message Date
f75a438422 obj renders 2026-02-23 16:53:57 -06:00
7a2131fc93 text appears 2026-02-23 12:50:16 -06:00
5 changed files with 93 additions and 173 deletions

View File

@@ -97,6 +97,7 @@ namespace Archimedes {
glBindTexture(GL_TEXTURE_2D, texture.id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture.getWidth(), texture.getHeight(), 0, GL_ALPHA, GL_UNSIGNED_BYTE, texture.getBin());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
void setupRenderTarget(RenderTarget& rt) override {
@@ -144,8 +145,9 @@ namespace Archimedes {
if(rt.texture.value().getActive()) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, rt.texture.value().id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, rt.texture.value().getWidth(), rt.texture.value().getHeight(), 0, GL_ALPHA, GL_UNSIGNED_BYTE, rt.texture.value().getBin());
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, rt.texture.value().getWidth(), rt.texture.value().getHeight(), 0, GL_RED, GL_UNSIGNED_BYTE, rt.texture.value().getBin());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
}

View File

@@ -30,7 +30,7 @@ namespace Archimedes {
std::abort();
}
#ifdef RENDERER_OPENGL
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

View File

@@ -4,6 +4,7 @@
#include "utils/Objects/Body.h"
#include <stb/stb_truetype.h>
#include <stb/stb_image_write.h>
#include <GL/glew.h>
@@ -14,11 +15,12 @@ namespace Archimedes {
unsigned int tex;
std::vector<unsigned char> ttf;
stbtt_bakedchar cdata[96];
stbtt_bakedchar bcdata[96];
std::string fontPath;
std::string vs = "#version 330 core\n"
std::string vs = "#version 430 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec2 aTex;\n"
"uniform mat4 model;\n"
@@ -27,19 +29,18 @@ namespace Archimedes {
"out vec2 TexCoord;\n"
"void main()\n"
"{\n"
" gl_Position = proj * view * model * vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
" gl_Position = proj * view * model * vec4(aPos.x, 1.0f - aPos.y, aPos.z, 1.0);\n"
" TexCoord = aTex;\n"
"}\0";
std::string fs = "#version 330 core\n"
std::string fs = "#version 430 core\n"
"out vec4 FragColor;\n"
"in vec2 TexCoord;\n"
"uniform sampler2D tex;\n"
"uniform vec4 color;\n"
"void main()\n"
"{\n"
" FragColor = vec4(0.6f, 0.1f, 0.1f, texture(tex, TexCoord).a);\n"
//" FragColor = vec4(1.0f);\n"
" FragColor = vec4(color.rgb, texture(tex, TexCoord).r);\n"
"}\n\0";
@@ -47,111 +48,11 @@ namespace Archimedes {
Shader shader;
Texture texture;
float fontSize = 200.0f;
Text() {}
~Text() {}
//////////////////////////////////////
// Load a TTF file into a texture and return the character data.
stbtt_packedchar* LoadFont(const char* filename) {
// Load TTF file into memory.
std::ifstream file(filename, std::ios::ate | std::ios::binary);
size_t fileSize = (size_t)file.tellg();
char* ttfData = (char*)calloc(fileSize + 1, sizeof(char));
file.seekg(0);
file.read(ttfData, fileSize);
file.close();
// Pack TTF into pixel data using stb_truetype.
stbtt_pack_context packContext;
stbtt_packedchar *charData = (stbtt_packedchar*)calloc(126, sizeof(stbtt_packedchar));
unsigned char* pixels = (unsigned char*)calloc(1024 * 1024, sizeof(char));
stbtt_PackBegin(&packContext, pixels, 1024, 1024, 1024, 1, NULL);
// Pack unicode codepoints 0 to 125 into the texture and character data. If a different starting
// point than 0 is picked then lookups in charData array must be offset by that number.
// With 0-125 the uppercase A will be at charData[65].
// With 32-125 the uppercase A will be at charData[65-32].
stbtt_PackFontRange(&packContext, (unsigned char*)ttfData, 0, 200.0f, 0, 125, charData);
stbtt_PackEnd(&packContext);
// Create OpenGL texture with the font pack pixel data.
// Only uses one color channel since font data is a monochrome alpha mask.
GLuint fontTexture;
glGenTextures(1, &fontTexture);
glBindTexture(GL_TEXTURE_2D, fontTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 1024, 1024, 0, GL_RED, GL_UNSIGNED_BYTE, pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
return charData;
}
// Calculate pixel width of a string.
float TextWidth(const char* text, float height, stbtt_packedchar *charData) {
float w = 0.0f;
for (int i = 0; i < strlen(text); i++) {
stbtt_packedchar c = charData[text[i]];
w += c.xadvance;
}
// Scale width by rendered height to texture generated height ratio for final size.
return w * (height / 200.0f);
}
// Render string using glDrawArrays.
// X indicates the leftmost, center or rightmost point of the based on align (0:left, 1:center, 2:rigght).
// Y is the baseline of the text.
void RenderString(const char* text, float x, float y, float height, int align, stbtt_packedchar *charData, GLuint program) {
// Scale of actual text compared to size on stb_truetype generated texture.
float scale = height / 200.0f;
// Resolution of window/display for shader position calculations.
float resolution[2] = { 1024, 1024 };
float position[2] = {x, y};
if (align == 1) {
// Center align
position[0] -= TextWidth(text, height, charData) / 2.0f;
} else if (align == 2) {
// Right align
position[0] -= TextWidth(text, height, charData);
}
glUniform2fv(glGetUniformLocation(program, "resolution"), 1, resolution);
for (int i = 0; i < strlen(text); i++) {
// Lookup current character data from stb_truetype.
stbtt_packedchar c = charData[text[i]];
// Position of character in texture.
float charPosition[4] = {static_cast<float>(c.x0), static_cast<float>(c.y0), static_cast<float>(c.x1), static_cast<float>(c.y1)};
// Find the actual size of character since fonts can be variable width.
// 'M' usually is wider than '!', 'L' taller than 'o', etc.
// Calculated by substracting start-offset from end-offset.
// xoff is start offset from the left.
// xoff2 is end offset from the left.
// yoff is start offset from the baseline (will be negative if above baseline).
// yoff2 is end offset from the baseline.
float size[2] = {(c.xoff2 - c.xoff) * scale, (c.yoff2 - c.yoff) * scale};
// The actual position of character based on its offset form left/baseline.
float renderPos[2] = {position[0] + c.xoff * scale, position[1] - c.yoff2 * scale};
glUniform4fv(glGetUniformLocation(program, "charPosition"), 1, charPosition);
glUniform2fv(glGetUniformLocation(program, "position"), 1, renderPos);
glUniform2fv(glGetUniformLocation(program, "size"), 1, size);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Advance x position to start of next character.
position[0] += c.xadvance * scale;
}
}
///////////////////////////////////////////
void textInit(std::string p) {
@@ -179,7 +80,7 @@ void RenderString(const char* text, float x, float y, float height, int align, s
file.close();
stbtt_BakeFontBitmap(ttf.data(),0, 200.0f, temp_bitmap,1024,1024, 32,96, cdata);
stbtt_BakeFontBitmap(ttf.data(),0, fontSize, temp_bitmap,1024,1024, 32,96, bcdata);
std::vector<unsigned char> bin;
bin.reserve(1024 * 1024);
@@ -188,76 +89,75 @@ void RenderString(const char* text, float x, float y, float height, int align, s
bin.push_back(c);
}
shader = Shader(vs, fs, Shader::LoadType::FromSource);
texture = Texture(bin, 1024, 1024);
shader = Shader(vs, fs, Shader::LoadType::FromSource);
}
Body* genText(std::vector<std::string> texts) {
// assume orthographic projection with units = screen pixels, origin at top left
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
std::vector<float> v;
std::vector<unsigned int> i;
float x = 0, y = 0, oX = 0, dY = 0;
float x = 0, y = 0, oX = 0, dY = fontSize;
std::string text = "";
unsigned int k = 0;
for(std::string s : texts) {
text += s + " ";
}
for(std::string text : texts) {
for(unsigned int j = 0; j < text.length(); j++) {
if (text[j] >= 32) {
stbtt_aligned_quad q;
stbtt_GetBakedQuad(bcdata, 1024,1024, text[j]-32, &x,&y,&q,0);//1=opengl & d3d10+,0=d3d9
for(unsigned int j = 0; j < text.length(); j++) {
if (text[j] >= 32) {
stbtt_aligned_quad q;
stbtt_GetBakedQuad(cdata, 512,512, text[j]-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
//bcdata[text[j]-32].xadvance
v.push_back(q.x0);
v.push_back(q.y0);
v.push_back(0.0f);
v.push_back(q.x0);
v.push_back(q.y0);
v.push_back(0.0f);
v.push_back(q.s0);
v.push_back(q.t0);
v.push_back(q.s0);
v.push_back(q.t0);
v.push_back(q.x1);
v.push_back(q.y0);
v.push_back(0.0f);
v.push_back(q.x1);
v.push_back(q.y0);
v.push_back(0.0f);
v.push_back(q.s1);
v.push_back(q.t0);
v.push_back(q.s1);
v.push_back(q.t0);
v.push_back(q.x1);
v.push_back(q.y1);
v.push_back(0.0f);
v.push_back(q.x1);
v.push_back(q.y1);
v.push_back(0.0f);
v.push_back(q.s1);
v.push_back(q.t1);
v.push_back(q.s1);
v.push_back(q.t1);
v.push_back(q.x0);
v.push_back(q.y1);
v.push_back(0.0f);
v.push_back(q.x0);
v.push_back(q.y1);
v.push_back(0.0f);
v.push_back(q.s0);
v.push_back(q.t1);
v.push_back(q.s0);
v.push_back(q.t1);
i.push_back(j * 4);
i.push_back(j * 4 + 1);
i.push_back(j * 4 + 2);
i.push_back(j * 4 + 2);
i.push_back(j * 4 + 3);
i.push_back(j * 4);
dY = q.y1 - q.y0;
i.push_back(k * 4);
i.push_back(k * 4 + 1);
i.push_back(k * 4 + 2);
i.push_back(k * 4 + 2);
i.push_back(k * 4 + 3);
i.push_back(k * 4);
k++;
}
}
x = oX;
y += dY;
}
@@ -269,9 +169,23 @@ void RenderString(const char* text, float x, float y, float height, int align, s
LayoutElement(LayoutElement::Type::Float, 2, 5 * sizeof(float), 3 * sizeof(float))
}),
shader,
texture
texture,
RenderMode::Triangles,
glm::scale(glm::mat4(1.0f), glm::vec3(0.2f))
);
}
float textWidth(std::string str, float height) {
float w = 0;
for (int i = 0; i < str.length(); i++) {
stbtt_bakedchar c = bcdata[str[i]];
w += c.xadvance;
}
return w * height / fontSize;
}
};
using json = nlohmann::json;

View File

@@ -6,6 +6,9 @@
#define STB_TRUETYPE_IMPLEMENTATION
#include <stb/stb_truetype.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb/stb_image_write.h>
Sandbox::Sandbox(Archimedes::App* a, void* h) : Archimedes::Module(a, h) {
name = "Sandbox";
@@ -108,7 +111,7 @@ void Sandbox::run() {
static glm::vec3 camPos(0.0f, 0.0f, 3.0f), camRot(0.0f, glm::pi<float>(), 0.0f);
static glm::vec3 camPosPrev(0.0f, 0.0f, 3.0f), camRotPrev(0.0f, glm::pi<float>(), 0.0f);
static glm::vec4 color = { 0.4f, 0.0f, 0.3f, 1.0f };
static glm::vec4 color = { 0.4f, 3.0f, 0.4f, 1.0f };
static int w, h;
window->getSize(w, h);
@@ -124,16 +127,6 @@ void Sandbox::run() {
camPosPrev = camPos;
camRotPrev = camRot;
/*
window->getRenderer()->draw(
hexagon.getMesh(),
hexagon.getTransform(),
camera.getTransform(),
camera.getPerspective(),
color
);
*/
{
ImGuiIO& io = ImGui::GetIO();
@@ -237,6 +230,18 @@ void Sandbox::run() {
}
}
static bool show_obj = true;
ImGui::Checkbox("show obj", &show_obj);
if(show_obj) {
window->getRenderer()->draw(
hexagon.getMesh(),
hexagon.getTransform(),
camera.getTransform(),
camera.getPerspective(),
color
);
}
ImGui::Text("Camera Properties");
ImGui::SliderFloat("cam pitch", &camRot.x, -glm::pi<float>(), glm::pi<float>());
@@ -268,11 +273,8 @@ bool Sandbox::onEvent(const Archimedes::Event& e) {
if(type == app->getEventType(Archimedes::ResizeWindowEvent())) {
Archimedes::ResizeWindowEvent event = (Archimedes::ResizeWindowEvent&) e;
for(auto o : jObject.objectMap) {
if(o.second != nullptr) {
o.second->scaleRel(1.0f / (float)event.height);
}
}
camera.setPerspective(glm::perspective(glm::radians(45.0f), (float)event.width/(float)event.height, 0.1f, 100.0f));
} else if(type == app->getEventType(Archimedes::KeyPressedWindowEvent()) && !io.WantCaptureKeyboard) {
return false;

View File

@@ -32,7 +32,7 @@ class Sandbox : public Archimedes::Module {
Archimedes::Window* window;
std::string cubeVS = "#version 330 core\n"
std::string cubeVS = "#version 430 core\n"
"layout (location = 0) in vec3 aPos;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
@@ -43,7 +43,7 @@ class Sandbox : public Archimedes::Module {
" gl_Position = proj * view * model * vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
std::string cubeFS = "#version 330 core\n"
std::string cubeFS = "#version 430 core\n"
"out vec4 FragColor;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
@@ -211,7 +211,9 @@ Archimedes::Body readOBJ(std::string path, Archimedes::Shader shader) {
return Archimedes::Body(
Archimedes::VertexBuffer(verticies),
Archimedes::IndexArray(indicies),
Archimedes::VertexLayout(),
Archimedes::VertexLayout({
Archimedes::LayoutElement(Archimedes::LayoutElement::Type::Float, 3, 3 * sizeof(float), 0),
}),
shader
);
}