add texture atlas for gpus without bindless textures

This commit is contained in:
Jay Robson 2024-03-22 01:12:48 +11:00
parent e2b16e0591
commit 2d69bb3c78
35 changed files with 699 additions and 277 deletions

Binary file not shown.

BIN
assets/scene.blend (Stored with Git LFS)

Binary file not shown.

BIN
assets/scene.glb (Stored with Git LFS)

Binary file not shown.

View File

@ -1,26 +0,0 @@
#version 460 core
uniform sampler2D tex;
uniform vec2 direction;
uniform int samples;
in vec2 FragPos;
out vec4 FragColour;
void main()
{
int radius = (samples - 1) / 2;
ivec2 size = textureSize(tex, 0);
vec2 step = direction / size;
vec4 sum = vec4(0.f);
for(int i = -radius; i <= radius; i++)
{
vec2 offset = vec2(i) * step;
sum += texture(tex, FragPos + offset);
}
FragColour = sum / float(samples);
}

View File

@ -1,21 +0,0 @@
#version 460 core
const vec2 QuadVertices[6] = vec2[6](
vec2(-1.0, 1.0),
vec2(-1.0, -1.0),
vec2( 1.0, -1.0),
vec2(-1.0, 1.0),
vec2( 1.0, -1.0),
vec2( 1.0, 1.0)
);
out vec2 FragPos;
void main()
{
vec2 vertex = QuadVertices[gl_VertexID];
FragPos = vertex * 0.5f + 0.5f;
gl_Position = vec4(vertex, 0.f, 1.f);
}

View File

@ -38,18 +38,19 @@ void Arrays::vertex_attrib_pointers()
glVertexAttribPointer(5, 3, GL_FLOAT, true, sizeof(v), ptr_diff(&v.tbn[2], &v));
glEnableVertexAttribArray(5);
glVertexAttribIPointer(6, 1, GL_INT, sizeof(v), ptr_diff(&v.transform_id, &v));
glVertexAttribPointer(6, 3, GL_FLOAT, false, sizeof(v), ptr_diff(&v.material, &v));
glEnableVertexAttribArray(6);
glVertexAttribIPointer(7, 1, GL_UNSIGNED_INT, sizeof(v), ptr_diff(&v.tex_diffuse, &v));
glVertexAttribIPointer(7, 1, GL_INT, sizeof(v), ptr_diff(&v.transform_id, &v));
glEnableVertexAttribArray(7);
glVertexAttribIPointer(8, 1, GL_UNSIGNED_INT, sizeof(v), ptr_diff(&v.tex_normal, &v));
glVertexAttribIPointer(8, 1, GL_UNSIGNED_INT, sizeof(v), ptr_diff(&v.tex_diffuse, &v));
glEnableVertexAttribArray(8);
glVertexAttribPointer(9, 3, GL_FLOAT, false, sizeof(v), ptr_diff(&v.material, &v));
glVertexAttribIPointer(9, 1, GL_UNSIGNED_INT, sizeof(v), ptr_diff(&v.tex_normal, &v));
glEnableVertexAttribArray(9);
}
std::ostream& Arrays::operator<<(std::ostream& os, const Vertex& v)

138
src/graphics/data/atlas.hpp Normal file
View File

@ -0,0 +1,138 @@
#pragma once
#include <vector>
namespace Sim::Graphics::Data
{
template <int N>
struct Atlas
{
struct Pixel
{
uint8_t data[N] = {0};
constexpr Pixel() = default;
constexpr Pixel(const Pixel& p)
{
for(int i = 0; i < N; i++)
{
data[i] = p.data[i];
}
}
constexpr Pixel(const uint8_t* p)
{
for(int i = 0; i < N; i++)
{
data[i] = p[i];
}
}
constexpr bool operator == (const Pixel& p) const
{
for(int i = 0; i < N; i++)
{
if(data[i] != p.data[i])
{
return false;
}
}
return true;
}
constexpr bool operator != (const Pixel& p) const
{
return !(*this == p);
}
constexpr Pixel& operator = (const Pixel& p)
{
for(int i = 0; i < N; i++)
{
data[i] = p.data[i];
}
return *this;
}
constexpr Pixel& operator = (const uint8_t* p)
{
for(int i = 0; i < N; i++)
{
data[i] = p[i];
}
return *this;
}
constexpr uint8_t& operator [] (int i)
{
return data[i];
}
constexpr const uint8_t& operator [] (int i) const
{
return data[i];
}
};
const int width;
const int height;
std::vector<Pixel> data;
Atlas(int width, int height)
: width(width)
, height(height)
, data(width * height)
{
}
Pixel& operator()(int x, int y)
{
return data[y * width + x];
}
const Pixel& operator()(int x, int y) const
{
return data[y * width + x];
}
void draw(const Atlas<N>& src, int x, int y, bool padding = false)
{
for(int i = 0; i < src.height; i++)
{
for(int j = 0; j < src.width; j++)
{
(*this)(x + j, y + i) = src(j, i);
}
}
if(padding)
{
for(int i = 0; i < src.height; i++)
{
(*this)(x - 1, y + i) = src(0, i);
(*this)(x + src.width, y + i) = src(src.width - 1, i);
}
for(int i = 0; i < src.width; i++)
{
(*this)(x + i, y - 1) = src(i, 0);
(*this)(x + i, y + src.height) = src(i, src.height - 1);
}
(*this)(x - 1, y - 1) = src(0, 0);
(*this)(x + src.width, y - 1) = src(src.width - 1, 0);
(*this)(x - 1, y + src.height) = src(0, src.height - 1);
(*this)(x + src.width, y + src.height) = src(src.width - 1, src.height - 1);
}
}
};
};

View File

@ -2,16 +2,18 @@
#pragma once
#include <glm/matrix.hpp>
#include <string>
namespace Sim::Graphics::Data
{
struct Camera
{
glm::vec3 pos;
glm::vec3 look;
glm::vec3 up;
float fov;
const std::string name;
const glm::vec3 pos;
const glm::vec3 look;
const glm::vec3 up;
const float fov;
float pitch = 0;
float yaw = 0;

View File

@ -8,25 +8,27 @@
#include <glm/vec2.hpp>
#include <iostream>
#include <vector>
#include <format>
#include "../shader.hpp"
#include "mesh.hpp"
#include "arrays.hpp"
#include "material.hpp"
#include "texture.hpp"
#include "font.hpp"
using namespace Sim::Graphics::Data;
struct Character
Font Fonts::BASE;
Font Fonts::MONO;
void Fonts::init()
{
uint32_t handle;
float advance;
glm::vec2 size;
glm::vec2 bearing;
};
BASE.init("DroidSans", 64);
MONO.init("DroidSansMono", 64);
}
static Character chars[128];
void Font::init()
void Font::init(const std::string& name, int size)
{
FT_Library ft;
FT_Face face;
@ -37,22 +39,15 @@ void Font::init()
return;
}
if(FT_New_Face(ft, "../assets/font/DroidSans.ttf", 0, &face))
if(FT_New_Face(ft, std::format("../assets/font/{}.ttf", name).c_str(), 0, &face))
{
std::cout << "Error: failed to load freetype font\n";
return;
}
int size = 256;
float m = 1.0f / size;
texel_size = 1.0f / size;
FT_Set_Pixel_Sizes(face, 0, size);
GLuint texids[128];
std::vector<glm::vec<4, unsigned char>> pixels;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for(int i = 0; i < 128; i++)
{
if(FT_Load_Char(face, (char)i, FT_LOAD_RENDER))
@ -65,61 +60,59 @@ void Font::init()
int offx = face->glyph->bitmap_left;
int offy = face->glyph->bitmap_top;
Character& c = chars[i];
c.advance = face->glyph->advance.x * m / 64.0;
c.size = {width * m, height * m};
c.bearing = {offx * m, offy * m};
Character& c = characters[i];
c.advance = face->glyph->advance.x * texel_size / 64.0;
c.size = {width * texel_size, height * texel_size};
c.bearing = {offx * texel_size, offy * texel_size};
if(c.size.x == 0 || c.size.y == 0)
{
c.handle = 0;
continue;
}
pixels.resize(width * height);
std::vector<uint8_t> buffer(width * height);
for(int i = 0; i < width * height; i++)
{
pixels[i] = glm::vec<4, unsigned char>(face->glyph->bitmap.buffer[i]);
buffer[i] = face->glyph->bitmap.buffer[i];
}
glCreateTextures(GL_TEXTURE_2D, 1, &texids[i]);
glTextureStorage2D(texids[i], 1, GL_RGBA8, width, height);
glTextureSubImage2D(texids[i], 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
glTextureParameteri(texids[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTextureParameteri(texids[i], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTextureParameteri(texids[i], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTextureParameteri(texids[i], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
c.handle = glGetTextureHandleARB(texids[i]);
glMakeTextureHandleResidentARB(c.handle);
chars[i] = c;
int swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_RED};
c.handle = Texture::load_mem(buffer.data(), width, height, 1, swizzleMask);
}
FT_Done_FreeType(ft);
}
Mesh& Mesh::load_text(const char* text, double size)
Font::Font()
{
std::vector<Arrays::Vertex> vertices;
std::vector<unsigned int> indices;
}
Mesh Font::load_text(const std::string& text, float size) const
{
Mesh m;
if(text[0] == '\0')
{
return m;
}
float x = 0, y = size;
unsigned int at = 0;
if(text[0] == '\0')
float t0 = 0;
float t1 = 1;
/*
if(!Shader::USE_BINDLESS_TEXTURES)
{
this->vertices.clear();
this->indices.clear();
return *this;
}
t0 += texel_size / 2;
t1 -= texel_size / 2;
}*/
for(unsigned int i = 0; text[i] != '\0'; i++)
for(unsigned int i = 0; i < text.size(); i++)
{
char c = text[i];
Character ch = chars[c];
const Character& ch = characters[c];
if(c == '\n')
{
@ -144,30 +137,25 @@ Mesh& Mesh::load_text(const char* text, double size)
float ex = sx + ch.size.x * size;
float ey = sy + ch.size.y * size;
vertices.push_back(Arrays::Vertex{.texpos={0, 0}, .pos={sx, sy, 0}, .tex_diffuse=ch.handle, .material={0, 0, 1}});
vertices.push_back(Arrays::Vertex{.texpos={0, 1}, .pos={sx, ey, 0}, .tex_diffuse=ch.handle, .material={0, 0, 1}});
vertices.push_back(Arrays::Vertex{.texpos={1, 0}, .pos={ex, sy, 0}, .tex_diffuse=ch.handle, .material={0, 0, 1}});
vertices.push_back(Arrays::Vertex{.texpos={1, 1}, .pos={ex, ey, 0}, .tex_diffuse=ch.handle, .material={0, 0, 1}});
indices.insert(indices.end(), &index[0], &index[6]);
m.vertices.push_back(Arrays::Vertex{.texpos={t0, t0}, .pos={sx, sy, 0}, .tex_diffuse=ch.handle, .material={0, 0, 1}});
m.vertices.push_back(Arrays::Vertex{.texpos={t0, t1}, .pos={sx, ey, 0}, .tex_diffuse=ch.handle, .material={0, 0, 1}});
m.vertices.push_back(Arrays::Vertex{.texpos={t1, t0}, .pos={ex, sy, 0}, .tex_diffuse=ch.handle, .material={0, 0, 1}});
m.vertices.push_back(Arrays::Vertex{.texpos={t1, t1}, .pos={ex, ey, 0}, .tex_diffuse=ch.handle, .material={0, 0, 1}});
m.indices.insert(m.indices.end(), &index[0], &index[6]);
at += 4;
x += ch.advance * size;
}
this->vertices = std::move(vertices);
this->indices = std::move(indices);
this->transforms.clear();
return *this;
return m;
}
Mesh& Mesh::load_text(const char* text, double size, glm::vec2 align)
Mesh Font::load_text(const std::string& text, float size, glm::vec2 align) const
{
glm::vec2 max;
load_text(text, size);
Mesh m = load_text(text, size);
for(Arrays::Vertex& v : vertices)
for(Arrays::Vertex& v : m.vertices)
{
if(v.pos.x > max.x)
{
@ -182,12 +170,12 @@ Mesh& Mesh::load_text(const char* text, double size, glm::vec2 align)
align *= max;
for(Arrays::Vertex& v : vertices)
for(Arrays::Vertex& v : m.vertices)
{
v.pos.x -= align.x;
v.pos.y -= align.y;
}
return *this;
return m;
}

View File

@ -6,10 +6,56 @@
#include <string>
#include <sstream>
namespace Sim::Graphics::Data::Font
#include <glm/vec2.hpp>
namespace Sim::Graphics::Data
{
void init();
class Font
{
struct Character
{
uint32_t handle;
glm::vec2 size;
glm::vec2 bearing;
float advance;
};
float texel_size;
Character characters[128];
public:
Font();
void init(const std::string& name, int size);
Mesh load_text(const std::string& text, float size, glm::vec2 align) const;
Mesh load_text(const std::string& text, float size) const;
template <class T>
void load_text(const char* header, T& item, double size)
{
std::stringstream ss;
ss << header << item;
load_text(ss.str(), size);
}
template <class T>
void load_text(const char* header, T& item, double size, glm::vec2 align)
{
std::stringstream ss;
ss << header << item;
load_text(ss.str(), size, align);
}
};
namespace Fonts
{
void init();
extern Font BASE;
extern Font MONO;
}
};

View File

View File

@ -28,8 +28,6 @@ struct Mesh
Mesh& set_blank_transform();
Mesh& set_normal_id(unsigned int id);
Mesh& set_diffuse_id(unsigned int id);
Mesh& load_text(const char* text, double size);
Mesh& load_text(const char* text, double size, glm::vec2 align);
Mesh& add(const Mesh& o, glm::mat4 mat = glm::mat4(1), bool bake = false);
Mesh to_lines() const;
@ -40,14 +38,6 @@ struct Mesh
bool operator==(const Mesh&) const = default;
template <class T>
void load_text(const char* header, T& item, double size)
{
std::stringstream ss;
ss << header << item;
load_text(ss.str().c_str(), size);
}
friend std::ostream& operator<<(std::ostream& os, const Mesh& m);
};

View File

@ -252,7 +252,13 @@ Model::Model(std::string base, std::string filename) : base(base)
glm::vec3 look = glm::normalize(glm::mat3(mat) * glm::vec3(dx, dy, dz));
glm::vec3 up = glm::normalize(glm::mat3(mat) * glm::vec3(ux, uy, uz));
cameras.push_back({.pos=glm::vec3(pos), .look=look, .up=up, .fov=camera->mHorizontalFOV});
cameras.push_back(Camera {
.name={camera->mName.C_Str()},
.pos=glm::vec3(pos),
.look=look,
.up=up,
.fov=camera->mHorizontalFOV
});
}
for(int i = 0; i < scene->mNumMaterials; i++)

View File

@ -2,33 +2,199 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stb/stb_image.h>
#include <stb/stb_rect_pack.h>
#include <glm/matrix.hpp>
#include <unordered_map>
#include <iostream>
#include <cmath>
#include "texture.hpp"
#include "atlas.hpp"
#include "../shader.hpp"
using namespace Sim::Graphics::Data;
static std::unordered_map<std::string, uint64_t> loaded;
uint64_t Texture::handle_white;
uint64_t Texture::handle_normal;
static bool is_done = false;
static uint32_t atlas_texid;
static uint32_t atlas_uv_ssbo;
static std::unordered_map<std::string, uint32_t> loaded;
static std::vector<Atlas<4>> texture_atlas_queue;
uint32_t Texture::handle_white;
uint32_t Texture::handle_normal;
void Texture::init()
{
unsigned char pixels_white[] = {255, 255, 255};
unsigned char pixels_normal[] = {128, 128, 255};
handle_white = load_mem(pixels_white, 1, 1, 3);
handle_normal = load_mem(pixels_normal, 1, 1, 3);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
unsigned char pixels_white[] = {255};
unsigned char pixels_normal[] = {128, 255};
int swizzle_white[] = {GL_RED, GL_RED, GL_RED, GL_RED};
int swizzle_normal[] = {GL_RED, GL_RED, GL_GREEN, GL_GREEN};
handle_white = load_mem(pixels_white, 1, 1, 1, swizzle_white);
handle_normal = load_mem(pixels_normal, 1, 1, 2, swizzle_normal);
}
uint64_t Texture::load_mem(const void* data, int width, int height, int channels)
void Texture::generate_atlas()
{
// if we are using bindless textures, we don't need to generate an atlas
if(Shader::USE_BINDLESS_TEXTURES)
{
return;
}
int total_area = 0;
int padding = 2;
int offset = 1;
for(const Atlas<4>& atlas : texture_atlas_queue)
{
total_area += (atlas.width + padding) * (atlas.height + padding);
}
int size = std::pow(2, std::ceil(std::log2(std::sqrt(total_area))));
std::vector<stbrp_rect> rects;
std::vector<glm::mat2> uvs;
rects.reserve(texture_atlas_queue.size());
uvs.reserve(texture_atlas_queue.size());
for(int i = 0; i < texture_atlas_queue.size(); i++)
{
const Atlas<4>& atlas = texture_atlas_queue[i];
stbrp_rect rect;
rect.id = i;
rect.w = atlas.width + padding;
rect.h = atlas.height + padding;
rects.push_back(rect);
}
stbrp_context context;
std::vector<stbrp_node> nodes(size);
for(;;)
{
stbrp_init_target(&context, size, size, nodes.data(), nodes.size());
if(stbrp_pack_rects(&context, rects.data(), rects.size()) == 1)
{
break;
}
size *= 2;
nodes.resize(size);
std::cout << "Error: failed to pack textures, trying again with size " << size << "\n";
}
Atlas<4> atlas(size, size);
for(const stbrp_rect& rect : rects)
{
const Atlas<4>& src = texture_atlas_queue[rect.id];
atlas.draw(src, rect.x + offset, rect.y + offset, true);
uvs.emplace_back(glm::mat2(
(rect.x + offset + 0.5f) / size, (rect.y + offset + 0.5f) / size,
(rect.x + offset + src.width - 0.5f) / size, (rect.y + offset + src.height - 0.5f) / size
));
}
std::cout << "Finished stitching " << size << "x" << size << " texture atlas\n";
glGenTextures(1, &atlas_texid);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, atlas_texid);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, atlas.data.data());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glGenBuffers(1, &atlas_uv_ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, atlas_uv_ssbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, uvs.size() * sizeof(uvs[0]), uvs.data(), GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, atlas_uv_ssbo);
glUniform1i(Shader::MAIN["tex_atlas"], 1);
is_done = true;
}
uint32_t Texture::load_mem(const uint8_t* data, int width, int height, int channels, int* swizzleMask)
{
if(is_done)
{
throw std::runtime_error("Texture loading is done");
}
if(!data)
{
return 0;
}
int swizzleMaskDefault[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
if(!swizzleMask)
{
swizzleMask = swizzleMaskDefault;
switch(channels)
{
case 1:
swizzleMask[1] = GL_ONE;
case 2:
swizzleMask[2] = GL_ONE;
case 3:
swizzleMask[3] = GL_ONE;
}
}
if(!Shader::USE_BINDLESS_TEXTURES)
{
Atlas<4> atlas(width, height);
for(int i = 0; i < width * height; i++)
{
int pixel_pos = i * channels;
Atlas<4>::Pixel pixel;
for(int j = 0; j < 4; j++)
{
switch(swizzleMask[j])
{
case GL_RED:
pixel[j] = data[pixel_pos];
break;
case GL_GREEN:
pixel[j] = data[pixel_pos + 1];
break;
case GL_BLUE:
pixel[j] = data[pixel_pos + 2];
break;
case GL_ALPHA:
pixel[j] = data[pixel_pos + 3];
break;
case GL_ZERO:
pixel[j] = 0;
break;
case GL_ONE:
pixel[j] = 255;
break;
}
}
atlas.data[i] = pixel;
}
texture_atlas_queue.push_back(std::move(atlas));
return texture_atlas_queue.size() - 1;
}
GLenum format;
GLenum format_in;
@ -56,22 +222,22 @@ uint64_t Texture::load_mem(const void* data, int width, int height, int channels
unsigned int texid;
glCreateTextures(GL_TEXTURE_2D, 1, &texid);
glTextureStorage2D(texid, 1, format_in, width, height);
glTextureSubImage2D(texid, 0, 0, 0, width, height, format, GL_UNSIGNED_BYTE, data);
glGenTextures(1, &texid);
glBindTexture(GL_TEXTURE_2D, texid);
glTexImage2D(GL_TEXTURE_2D, 0, format_in, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTextureParameteriv(texid, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
glGenerateMipmap(GL_TEXTURE_2D);
glTextureParameteri(texid, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTextureParameteri(texid, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTextureParameteri(texid, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTextureParameteri(texid, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateTextureMipmap(texid);
uint64_t handle = glGetTextureHandleARB(texid);
uint32_t handle = glGetTextureHandleARB(texid);
glMakeTextureHandleResidentARB(handle);
return handle;
}
uint64_t Texture::load_mem(const unsigned char* filedata, size_t len)
uint32_t Texture::load_mem(const uint8_t* filedata, size_t len)
{
int width, height, channels;
unsigned char* data = stbi_load_from_memory(filedata, len, &width, &height, &channels, 0);
@ -80,7 +246,7 @@ uint64_t Texture::load_mem(const unsigned char* filedata, size_t len)
return handle;
}
uint64_t Texture::load(std::string path)
uint32_t Texture::load(std::string path)
{
const auto it = loaded.find(path);

View File

@ -4,17 +4,19 @@
#include <GL/glew.h>
#include <string>
#include <glm/vec2.hpp>
namespace Sim::Graphics::Data::Texture
{
extern uint64_t handle_white;
extern uint64_t handle_normal;
extern uint32_t handle_white;
extern uint32_t handle_normal;
void init();
uint64_t load(std::string path);
uint64_t load_mem(const void* data, int width, int height, int channels);
uint64_t load_mem(const unsigned char* data, size_t len);
void generate_atlas();
uint32_t load(std::string path);
uint32_t load_mem(const uint8_t* data, int width, int height, int channels, int* swizzleMask = nullptr);
uint32_t load_mem(const uint8_t* data, size_t len);
};

View File

@ -13,6 +13,7 @@
#include "../camera.hpp"
#include "../input/focus.hpp"
#include "../data/texture.hpp"
#include "../data/font.hpp"
#include "../../system.hpp"
#include "../../util/math.hpp"
#include "../../util/streams.hpp"
@ -49,7 +50,7 @@ public:
if(zoom)
{
Data::Camera& active = parent->cameras[parent->camera_at];
active.zoom = Util::Math::clamp(1.f / (1.f / active.zoom - zoom * dt * 0.5f), 1.f, 4.f);
active.zoom = Util::Math::clamp(active.zoom - zoom * dt * 0.5f, 0.25, 1);
}
}
@ -63,7 +64,7 @@ public:
parent->camera_at = (parent->camera_at + parent->cameras.size() - 1) % parent->cameras.size();
break;
case GLFW_KEY_KP_2:
rot_pitch -= 1;
parent->powered = !parent->powered;
break;
case GLFW_KEY_KP_3:
parent->camera_at = (parent->camera_at + 1) % parent->cameras.size();
@ -72,7 +73,7 @@ public:
rot_yaw += 1;
break;
case GLFW_KEY_KP_5:
parent->powered = !parent->powered;
rot_pitch -= 1;
break;
case GLFW_KEY_KP_6:
rot_yaw -= 1;
@ -93,12 +94,12 @@ public:
{
switch(key)
{
case GLFW_KEY_KP_2:
rot_pitch += 1;
break;
case GLFW_KEY_KP_4:
rot_yaw -= 1;
break;
case GLFW_KEY_KP_5:
rot_pitch += 1;
break;
case GLFW_KEY_KP_6:
rot_yaw += 1;
break;
@ -150,6 +151,7 @@ CCTV::CCTV(Model& model)
handle = glGetTextureHandleARB(texture);
glMakeTextureHandleResidentARB(handle);
mat = model.load_matrix("translation_monitor_1");
m_screen.vertices = {
{.texpos={0, 1}, .pos={0, 0, 0}, .transform_id=0, .tex_diffuse=handle, .material={0, 0, 1}},
{.texpos={0, 0}, .pos={0, 1, 0}, .transform_id=0, .tex_diffuse=handle, .material={0, 0, 1}},
@ -157,7 +159,7 @@ CCTV::CCTV(Model& model)
{.texpos={1, 0}, .pos={1, 1, 0}, .transform_id=0, .tex_diffuse=handle, .material={0, 0, 1}},
};
m_screen.indices = {0, 1, 3, 0, 3, 2};
m_screen.transforms = {model.load_matrix("translation_monitor_1")};
m_screen.transforms = {mat};
m_screen.bake_transforms();
gm_screen.bind();
@ -194,12 +196,50 @@ CCTV::CCTV(CCTV&& o)
void CCTV::rotate(double dt, float pitch, float yaw)
{
Data::Camera& active = cameras[camera_at];
float m = float(M_PI) * dt * 0.5f / active.zoom;
float m = float(M_PI) * dt * 0.5f * active.zoom;
active.pitch = Util::Math::clamp(active.pitch + pitch * m, -M_PI / 4, M_PI / 4);
active.yaw = Util::Math::clamp(active.yaw + yaw * m, -M_PI / 4, M_PI / 4);
}
void CCTV::remesh_slow(Data::Mesh& rmesh)
{
if(!powered)
{
return;
}
const Data::Camera& active = cameras[camera_at];
std::stringstream ss;
ss << "- ";
for(int i = 0; i < cameras.size(); i++)
{
if(i == camera_at)
{
ss << "[" << cameras[i].name << "] ";
}
else
{
ss << " " << cameras[i].name << " ";
}
}
ss << "-\n";
rmesh.add(Data::Fonts::MONO.load_text(ss.str(), 0.02, {0.5, 0}), glm::translate(mat, {0.5, 0.95, 0}), true);
char zoom_chars[] = " ";
zoom_chars[(int)std::round(Util::Math::ramp(active.zoom, 1, 0.25, 0, 9))] = '#';
ss.str("");
ss << "Zoom: [" << zoom_chars << "]";
rmesh.add(Data::Fonts::MONO.load_text(ss.str(), 0.02), glm::translate(mat, {0.0125, 0.0125, 0}), true);
}
void CCTV::update(double dt)
{
Data::Camera& active = cameras[camera_at];
@ -207,21 +247,21 @@ void CCTV::update(double dt)
if(m_screen.check_focus())
Focus::set(std::make_unique<FocusCCTV>(this));
if(m_buttons[0].check_focus_hold())
active.zoom = Util::Math::clamp(1.f / (1.f / active.zoom - dt * 0.5f), 1.f, 4.f);
active.zoom = Util::Math::clamp(active.zoom - dt * 0.5f, 0.25, 1);
if(m_buttons[1].check_focus_hold())
rotate(dt, 1, 0);
if(m_buttons[2].check_focus_hold())
active.zoom = Util::Math::clamp(1.f / (1.f / active.zoom + dt * 0.5f), 1.f, 4.f);
active.zoom = Util::Math::clamp(active.zoom + dt * 0.5f, 0.25, 1);
if(m_buttons[3].check_focus_hold())
rotate(dt, 0, -1);
if(m_buttons[4].check_focus())
powered = !powered;
if(m_buttons[4].check_focus_hold())
rotate(dt, -1, 0);
if(m_buttons[5].check_focus_hold())
rotate(dt, 0, 1);
if(m_buttons[6].check_focus())
camera_at = (camera_at + cameras.size() - 1) % cameras.size();
if(m_buttons[7].check_focus_hold())
rotate(dt, -1, 0);
if(m_buttons[7].check_focus())
powered = !powered;
if(m_buttons[8].check_focus())
camera_at = (camera_at + 1) % cameras.size();
}
@ -239,7 +279,7 @@ void CCTV::render_view()
rot = glm::rotate(rot, active.pitch, right);
glm::mat4 view = glm::lookAt(active.pos, active.pos + glm::mat3(rot) * active.look, active.up);
glm::mat4 proj = glm::perspective(active.fov / active.zoom, (float)width / height, 0.1f, 100.0f);
glm::mat4 proj = glm::perspective(active.fov * active.zoom, (float)width / height, 0.1f, 100.0f);
glm::vec3 brightness = glm::vec3(System::active->grid.get_light_intensity());
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

View File

@ -1,6 +1,8 @@
#pragma once
#include <glm/matrix.hpp>
#include <vector>
#include <array>
@ -27,6 +29,7 @@ class CCTV : public Data::MeshGen
public:
glm::mat4 mat;
std::vector<Data::Camera> cameras;
int camera_at = 0;
bool powered = false;
@ -37,6 +40,7 @@ public:
~CCTV();
void update(double dt) override;
void remesh_slow(Data::Mesh& rmesh) override;
void rotate(double dt, float pitch, float yaw);
void render_view();
void render_screen();

View File

@ -8,6 +8,7 @@
#include "../data/texture.hpp"
#include "../../system.hpp"
#include "../../util/streams.hpp"
#include "../data/font.hpp"
#include <glm/ext/matrix_transform.hpp>
@ -66,7 +67,7 @@ struct CoreMonitor : public Focus::FocusType
sys.reactor.move_cursor(-1);
break;
case GLFW_KEY_KP_5:
sys.reactor.toggle_selected();
sys.reactor.move_cursor(sys.reactor.height);
break;
case GLFW_KEY_KP_6:
sys.reactor.move_cursor(1);
@ -75,7 +76,7 @@ struct CoreMonitor : public Focus::FocusType
sys.reactor.reset_rod_speed();
break;
case GLFW_KEY_KP_2:
sys.reactor.move_cursor(sys.reactor.height);
sys.reactor.toggle_selected();
break;
default:
return;
@ -135,9 +136,7 @@ Core::Core(const Model& model)
void Core::remesh_static(Mesh& rmesh)
{
Data::Mesh mesh;
mesh.load_text("Reactor Core", 0.04);
rmesh.add(mesh, mat, true);
rmesh.add(Data::Fonts::BASE.load_text("Reactor Core", 0.04), mat, true);
}
static Data::Mesh add_dot(glm::mat4 model_mat, glm::vec4 colour)
@ -174,13 +173,13 @@ void Core::update(double dt)
if(m_buttons[3].check_focus())
sys.reactor.move_cursor(-1);
if(m_buttons[4].check_focus())
sys.reactor.toggle_selected();
sys.reactor.move_cursor(sys.reactor.height);
if(m_buttons[5].check_focus())
sys.reactor.move_cursor(1);
if(m_buttons[6].check_focus())
sys.reactor.reset_rod_speed();
if(m_buttons[7].check_focus())
sys.reactor.move_cursor(sys.reactor.height);
sys.reactor.toggle_selected();
}
void Core::remesh_slow(Mesh& rmesh)

View File

@ -7,6 +7,7 @@
#include "../../coolant/valve.hpp"
#include "../input/focus.hpp"
#include "../../util/streams.hpp"
#include "../data/font.hpp"
#include <glm/ext/matrix_transform.hpp>
#include <iostream>
@ -67,7 +68,6 @@ PrimaryLoop::PrimaryLoop(const Model& model)
void PrimaryLoop::remesh_static(Mesh& rmesh)
{
std::stringstream ss;
Data::Mesh mesh;
ss << "Turbine Bypass Valve\n\n";
ss << "Opened\nFlow\nSetpoint\n\n";
@ -81,8 +81,7 @@ void PrimaryLoop::remesh_static(Mesh& rmesh)
ss << "Pressure\n";
ss << "Level\n";
mesh.load_text(ss.str().c_str(), 0.04);
rmesh.add(mesh, mat, true);
rmesh.add(Data::Fonts::BASE.load_text(ss.str(), 0.04), mat, true);
rmesh.add(g_switch_pump);
rmesh.add(g_switch_bypass);
@ -108,7 +107,6 @@ void PrimaryLoop::update(double dt)
void PrimaryLoop::remesh_slow(Mesh& rmesh)
{
std::stringstream ss;
Sim::Graphics::Data::Mesh mesh;
System& sys = *System::active;
ss << "\n\n";
@ -149,7 +147,7 @@ void PrimaryLoop::remesh_slow(Mesh& rmesh)
show_units( ss, sys.loop.condenser.get_pressure() ) << "Pa\n";
ss << show( sys.loop.condenser.get_level() / 1000 ) << " / " << show( sys.loop.condenser.get_volume() / 1000 ) << " kL\n";
mesh.load_text(ss.str().c_str(), 0.04);
Mesh mesh = Data::Fonts::BASE.load_text(ss.str(), 0.04);
rmesh.add(mesh, glm::translate(mat, glm::vec3(0.5, 0, 0)));
}

View File

@ -7,6 +7,7 @@
#include "../../coolant/valve.hpp"
#include "../input/focus.hpp"
#include "../../util/streams.hpp"
#include "../data/font.hpp"
#include <glm/ext/matrix_transform.hpp>
#include <iostream>
@ -42,7 +43,6 @@ void SecondaryLoop::update(double dt)
void SecondaryLoop::remesh_static(Mesh& rmesh)
{
std::stringstream ss;
Data::Mesh mesh;
ss << "Cooling Tower\n\n";
ss << "Heat\nSteam\nPressure\nLevel\n\n";
@ -51,8 +51,7 @@ void SecondaryLoop::remesh_static(Mesh& rmesh)
ss << "Freight Pump\n\n";
ss << "Power\nSpeed\nFlow\n\n";
mesh.load_text(ss.str().c_str(), 0.04);
rmesh.add(mesh, mat, true);
rmesh.add(Data::Fonts::BASE.load_text(ss.str(), 0.04), mat, true);
rmesh.add(g_switch_2);
rmesh.add(g_switch_3);
}
@ -60,7 +59,6 @@ void SecondaryLoop::remesh_static(Mesh& rmesh)
void SecondaryLoop::remesh_slow(Mesh& rmesh)
{
std::stringstream ss;
Sim::Graphics::Data::Mesh mesh;
System& sys = *System::active;
ss << "\n\n";
@ -77,7 +75,7 @@ void SecondaryLoop::remesh_slow(Mesh& rmesh)
ss << show( sys.freight_pump.get_rpm() ) << " r/min\n";
show_units( ss, sys.freight_pump.get_flow_mass() ) << "g/s\n";
mesh.load_text(ss.str().c_str(), 0.04);
Mesh mesh = Data::Fonts::BASE.load_text(ss.str().c_str(), 0.04);
rmesh.add(mesh, glm::translate(mat, glm::vec3(0.5, 0, 0)));
}

View File

@ -8,6 +8,7 @@
#include "../input/focus.hpp"
#include "../../util/streams.hpp"
#include "../../util/math.hpp"
#include "../data/font.hpp"
#include <glm/ext/matrix_transform.hpp>
#include <iostream>
@ -69,13 +70,11 @@ void Turbine::get_static_transforms(std::vector<glm::mat4>& transforms)
void Turbine::remesh_static(Mesh& rmesh)
{
std::stringstream ss;
Sim::Graphics::Data::Mesh mesh;
ss << "Turbine\n\n";
ss << "Heat\nPressure\nSpeed\n\n";
mesh.load_text(ss.str().c_str(), 0.04);
rmesh.add(mesh, mat, true);
rmesh.add(Data::Fonts::BASE.load_text(ss.str(), 0.04), mat, true);
rmesh.add(g_dial_phase);
rmesh.add(g_dial_voltage);
@ -87,7 +86,6 @@ void Turbine::remesh_static(Mesh& rmesh)
void Turbine::remesh_slow(Mesh& rmesh)
{
std::stringstream ss;
Sim::Graphics::Data::Mesh mesh;
System& sys = *System::active;
ss << "\n\n";
@ -95,7 +93,7 @@ void Turbine::remesh_slow(Mesh& rmesh)
ss << show( sys.loop.turbine.get_pressure() / 1000 ) << " kPa\n";
ss << show( sys.loop.generator.get_rpm() ) << " r/min\n";
mesh.load_text(ss.str().c_str(), 0.04);
Mesh mesh = Data::Fonts::BASE.load_text(ss.str(), 0.04);
rmesh.add(mesh, glm::translate(mat, glm::vec3(0.5, 0, 0)));
}

View File

@ -7,6 +7,7 @@
#include "../../reactor/control/boron_rod.hpp"
#include "../../system.hpp"
#include "../../util/streams.hpp"
#include "../data/font.hpp"
#include <glm/ext/matrix_transform.hpp>
#include <sstream>
@ -23,7 +24,6 @@ Vessel::Vessel(const Model& model)
void Vessel::remesh_static(Mesh& rmesh)
{
std::stringstream ss;
Sim::Graphics::Data::Mesh mesh;
ss << "Reactor Vessel\n\n";
ss << "Heat\n";
@ -37,14 +37,12 @@ void Vessel::remesh_static(Mesh& rmesh)
ss << "Temperature\nMin\nMax\n\n";
ss << "Control Rods\nMin\nMax\nSpeed\n";
mesh.load_text(ss.str().c_str(), 0.04);
rmesh.add(mesh, mat, true);
rmesh.add(Data::Fonts::BASE.load_text(ss.str(), 0.04), mat, true);
}
void Vessel::remesh_slow(Mesh& rmesh)
{
std::stringstream ss;
Sim::Graphics::Data::Mesh mesh;
Sim::System& sys = *System::active;
double temp_min, temp_max;
@ -92,7 +90,7 @@ void Vessel::remesh_slow(Mesh& rmesh)
if(sys.reactor.rod_speed == 0) ss << " (Stopped)";
ss << "\n";
mesh.load_text(ss.str().c_str(), 0.04);
Mesh mesh = Data::Fonts::BASE.load_text(ss.str(), 0.04);
rmesh.add(mesh, glm::translate(mat, glm::vec3(0.5, 0, 0)));
}

View File

@ -8,6 +8,7 @@
#include <format>
#include "shader.hpp"
#include "shadersource.hpp"
#include "window.hpp"
using namespace Sim::Graphics;
@ -16,40 +17,54 @@ Shader Shader::MAIN;
Shader Shader::LIGHT;
Shader* Shader::ACTIVE;
static std::string read_shader(const char* path)
bool Shader::USE_BINDLESS_TEXTURES = false;
static std::vector<std::string> shader_compiler_flags;
void Shader::add_define(const std::string& flag)
{
shader_compiler_flags.push_back(flag);
}
void Shader::init()
{
Shader::Source sources_main[] = {
{ShaderSource::MAIN_VSH, "main.vsh", GL_VERTEX_SHADER},
{ShaderSource::MAIN_FSH, "main.fsh", GL_FRAGMENT_SHADER}
};
Shader::Source sources_light[] = {
{ShaderSource::LIGHT_VSH, "light.vsh", GL_VERTEX_SHADER},
{ShaderSource::LIGHT_GSH, "light.gsh", GL_GEOMETRY_SHADER},
{ShaderSource::LIGHT_FSH, "light.fsh", GL_FRAGMENT_SHADER}
};
Shader::MAIN.load(sources_main, "main", 2);
Shader::LIGHT.load(sources_light, "light", 3);
}
std::string apply_shader_compiler_flags(const char* source)
{
std::stringstream ss;
std::ifstream file(path, std::ios::binary);
char buff[1024];
ss << "#version 430 core\n";
if(!file.is_open())
for(const auto& flag : shader_compiler_flags)
{
throw std::runtime_error(std::format("Shader Read Error: {0}", path));
}
while(!file.eof())
{
file.read(buff, 1024);
ss.write(buff, file.gcount());
ss << "#define " << flag << "\n";
}
ss << source;
return ss.str();
}
static std::string read_shader(const char* base, const char* file)
{
std::string path = std::string(base) + "/" + std::string(file);
return read_shader(path.c_str());
}
Shader::Source::Source(const char* path, GLenum type)
Shader::Source::Source(const char* data, const char* name, GLenum type)
{
int success;
std::string src = read_shader(path);
const char* c_src = src.c_str();
std::string source = apply_shader_compiler_flags(data);
data = source.c_str();
id = glCreateShader(type);
glShaderSource(id, 1, &c_src, nullptr);
glShaderSource(id, 1, &data, nullptr);
glCompileShader(id);
glGetShaderiv(id, GL_COMPILE_STATUS, &success);
@ -57,7 +72,7 @@ Shader::Source::Source(const char* path, GLenum type)
{
char infoLog[512];
glGetShaderInfoLog(id, 512, NULL, infoLog);
std::string entry = std::format("Shader Compile Error ({0}): {1}", path, infoLog);
std::string entry = std::format("Shader Compile Error ({0}): {1}", name, infoLog);
throw std::runtime_error(entry);
}
}
@ -92,7 +107,7 @@ Shader::~Shader()
}
}
void Shader::load(const Source* sources, int count)
void Shader::load(const Source* sources, const char* name, int count)
{
int success;
prog_id = glCreateProgram();
@ -109,7 +124,7 @@ void Shader::load(const Source* sources, int count)
{
char infoLog[512];
glGetProgramInfoLog(prog_id, 512, NULL, infoLog);
std::string entry = std::format("Shader Link Error: {0}", infoLog);
std::string entry = std::format("Shader Link Error {0}: {1}", name, infoLog);
throw std::runtime_error(entry);
}
}

View File

@ -4,6 +4,7 @@
#include <GL/glew.h>
#include <unordered_map>
#include <string>
namespace Sim::Graphics
{
@ -22,7 +23,7 @@ public:
{
unsigned int id;
Source(const char* path, GLenum type);
Source(const char* data, const char* name, GLenum type);
Source(const Source& o) = delete;
Source(Source&& o);
~Source();
@ -33,12 +34,17 @@ public:
static Shader* ACTIVE;
static bool USE_BINDLESS_TEXTURES;
Shader();
Shader(const Shader& o) = delete;
Shader(Shader&& o);
~Shader();
void load(const Source* sources, int count);
static void add_define(const std::string& flag);
static void init();
void load(const Source* sources, const char* name, int count);
void block_binding(const char* name, unsigned int index);
void use();

View File

@ -1,5 +1,4 @@
#version 460 core
R"GLSL(
in vec3 frag_pos;
@ -11,3 +10,4 @@ void main()
gl_FragDepth = distance / far_plane;
}
)GLSL";

View File

@ -1,5 +1,4 @@
#version 460 core
R"GLSL(
layout (triangles) in;
layout (triangle_strip, max_vertices=18) out;
@ -33,3 +32,4 @@ void main()
}
}
)GLSL";

View File

@ -1,11 +1,8 @@
#version 460 core
#define MAX_LIGHTS 6
R"GLSL(
layout (location = 1) in vec3 aPos;
layout (location = 2) in vec4 aColour;
layout (location = 6) in int aTransformIndex;
layout (location = 7) in int aTransformIndex;
layout (binding = 3) readonly buffer TransformBuffer
{
@ -31,3 +28,4 @@ void main()
should_ignore = int(aColour.a < 1.f);
}
)GLSL";

View File

@ -1,6 +1,8 @@
R"GLSL(
#version 460 core
#ifdef USE_BINDLESS_TEXTURES
#extension GL_ARB_bindless_texture : require
#endif
const float PI = 3.141592f;
@ -23,9 +25,40 @@ layout(std140, binding = 2) readonly buffer LightBuffer
Light lights[];
};
#ifdef USE_BINDLESS_TEXTURES
in flat sampler2D frag_tex_diffuse;
in flat sampler2D frag_tex_normal;
#define ReadTexture(tex, uv) texture(tex, uv)
#else
in flat uint frag_tex_diffuse;
in flat uint frag_tex_normal;
uniform sampler2D tex_atlas;
struct AtlasPart
{
vec2 uv_min;
vec2 uv_max;
};
layout(std140, binding = 5) readonly buffer AtlasBuffer
{
AtlasPart atlas[];
};
vec4 ReadTexture(uint tex, vec2 uv)
{
AtlasPart a = atlas[tex];
uv = mod(uv, 1.f) * (a.uv_max - a.uv_min) + a.uv_min;
return texture(tex_atlas, uv);
}
#endif
out vec4 frag_colour;
uniform vec3 brightness;
@ -107,10 +140,10 @@ vec3 sRGB_To_LinRGB(vec3 c)
void main()
{
vec4 albedo = texture2D(frag_tex_diffuse, vin.tex_pos);
vec4 albedo = ReadTexture(frag_tex_diffuse, vin.tex_pos);
if(albedo.a == 0.f) discard;
vec3 tangent = texture2D(frag_tex_normal, vin.tex_pos).rgb * 2.f - 1.f;
vec3 tangent = ReadTexture(frag_tex_normal, vin.tex_pos).rgb * 2.f - 1.f;
vec3 albedo_lin = sRGB_To_LinRGB(albedo.rgb) * vin.colour.rgb;
albedo *= vin.colour;
@ -180,3 +213,4 @@ void main()
frag_colour = vec4(light, albedo.a);
}
)GLSL";

View File

@ -1,6 +1,8 @@
R"GLSL(
#version 460 core
#ifdef USE_BINDLESS_TEXTURES
#extension GL_ARB_bindless_texture : require
#endif
layout (location = 0) in vec2 aTexPos;
layout (location = 1) in vec3 aPos;
@ -8,10 +10,26 @@ layout (location = 2) in vec4 aColour;
layout (location = 3) in vec3 aTangent;
layout (location = 4) in vec3 aBitangent;
layout (location = 5) in vec3 aNormal;
layout (location = 6) in int aTransformIndex;
layout (location = 7) in sampler2D aTexDiffuse;
layout (location = 8) in sampler2D aTexNormal;
layout (location = 9) in vec3 aMaterial;
layout (location = 6) in vec3 aMaterial;
layout (location = 7) in int aTransformIndex;
#ifdef USE_BINDLESS_TEXTURES
layout (location = 8) in sampler2D aTexDiffuse;
layout (location = 9) in sampler2D aTexNormal;
out flat sampler2D frag_tex_diffuse;
out flat sampler2D frag_tex_normal;
#else
layout (location = 8) in uint aTexDiffuse;
layout (location = 9) in uint aTexNormal;
out flat uint frag_tex_diffuse;
out flat uint frag_tex_normal;
#endif
uniform mat4 camera;
uniform mat4 projection;
@ -29,9 +47,6 @@ out VS_OUT {
flat vec3 material;
} vout;
out flat sampler2D frag_tex_diffuse;
out flat sampler2D frag_tex_normal;
mat4 load_model_mat(int index)
{
return index < 0 ? mat4(1.f) : transforms[index];
@ -60,3 +75,4 @@ void main()
gl_Position = mvp * pos;
}
)GLSL";

View File

@ -0,0 +1,17 @@
#include "shadersource.hpp"
using namespace Sim::Graphics;
const char* ShaderSource::LIGHT_VSH =
#include "shaders/light.vsh"
const char* ShaderSource::LIGHT_GSH =
#include "shaders/light.gsh"
const char* ShaderSource::LIGHT_FSH =
#include "shaders/light.fsh"
const char* ShaderSource::MAIN_VSH =
#include "shaders/main.vsh"
const char* ShaderSource::MAIN_FSH =
#include "shaders/main.fsh"

View File

@ -0,0 +1,12 @@
#pragma once
namespace Sim::Graphics::ShaderSource
{
extern const char* LIGHT_VSH;
extern const char* LIGHT_GSH;
extern const char* LIGHT_FSH;
extern const char* MAIN_VSH;
extern const char* MAIN_FSH;
};

View File

@ -27,7 +27,6 @@ void Clock::update(double dt)
void Clock::remesh_slow(Mesh& rmesh)
{
Mesh m;
double at = System::active->clock;
glm::vec2 wsize(Resize::get_size() / 2);
std::stringstream ss;
@ -42,7 +41,7 @@ void Clock::remesh_slow(Mesh& rmesh)
ss << std::setfill('0') << std::setw(2) << t_s << "\n";
ss << "Day: " << std::floor(at / (3600 * 24)) << "\n";
m.load_text(ss.str().c_str(), 20);
Mesh m = Fonts::BASE.load_text(ss.str(), 20);
rmesh.add(m, glm::translate(glm::mat4(1), glm::vec3(-wsize + glm::vec2(2, 2), 0)));
}

View File

@ -105,7 +105,7 @@ void Window::create()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true);
glfwWindowHint(GLFW_VISIBLE, false);
@ -129,17 +129,15 @@ void Window::create()
return;
}
if(!glGetTextureHandleARB || !glMakeTextureHandleResidentARB)
if(glGetTextureHandleARB && glMakeTextureHandleResidentARB)
{
std::cerr << "Fatal: Bindless textures not supported\n";
Shader::add_define("USE_BINDLESS_TEXTURES");
Shader::USE_BINDLESS_TEXTURES = true;
}
if(!glGetTextureHandleARB)
std::cerr << " Missing: glGetTextureHandleARB\n";
if(!glMakeTextureHandleResidentARB)
std::cerr << " Missing: glMakeTextureHandleResidentARB\n";
close();
return;
else
{
std::cout << "Warning: Bindless textures are not supported. Using texture atlas instead.\n";
}
glEnable(GL_MULTISAMPLE);
@ -156,21 +154,9 @@ void Window::create()
Mouse::init();
Resize::init();
Texture::init();
Font::init();
Fonts::init();
UI::init();
// load all the shaders
Shader::Source sources_main[] = {
{"../assets/shader/main.vsh", GL_VERTEX_SHADER},
{"../assets/shader/main.fsh", GL_FRAGMENT_SHADER},
};
Shader::Source sources_light[] = {
{"../assets/shader/light.vsh", GL_VERTEX_SHADER},
{"../assets/shader/light.gsh", GL_GEOMETRY_SHADER},
{"../assets/shader/light.fsh", GL_FRAGMENT_SHADER},
};
Shader::MAIN.load(sources_main, 2);
Shader::LIGHT.load(sources_light, 3);
Shader::init();
Shader::MAIN.use();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@ -204,6 +190,8 @@ void Window::create()
equipment.push_back(new Equipment::Generator(model));
equipment.push_back(new Equipment::Pool(model));
Texture::generate_atlas();
remesh_static();
glfwShowWindow(win);

View File

@ -0,0 +1,4 @@
#define STB_RECT_PACK_IMPLEMENTATION
#include <stb/stb_rect_pack.h>

View File

@ -48,5 +48,11 @@ constexpr A mod(A a, auto b)
return v;
}
template <typename A>
constexpr A ramp(A v, auto imin, auto imax, auto omin, auto omax)
{
return clamp(map(v, imin, imax, omin, omax), omin, omax);
}
};