128 lines
4.5 KiB
C++
128 lines
4.5 KiB
C++
#include <textures.h>
|
|
#include <stb_image.h>
|
|
#include <opengl.h>
|
|
#include <assert.h>
|
|
|
|
RenderBatch* texture_quad_batch = NULL;
|
|
int max_textures;
|
|
|
|
void setup_textures() {
|
|
texture_quad_batch = create_texture_quad_batch();
|
|
|
|
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_textures);
|
|
if(max_textures > 32) max_textures = 32;
|
|
}
|
|
|
|
uint32_t load_texture(const char* path) {
|
|
uint32_t id;
|
|
glCreateTextures(GL_TEXTURE_2D, 1, &id);
|
|
|
|
uint8_t default_texture[] = {
|
|
0, 0, 0, 255, 255, 0, 255, 255,
|
|
255, 0, 255, 255, 0, 0, 0, 255 };
|
|
|
|
int width = 2, height = 2, channels;
|
|
uint8_t* pixels = stbi_load(path, &width, &height, &channels, 4);
|
|
if(pixels) {
|
|
glTextureParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTextureParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTextureParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTextureParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glTextureStorage2D(id, 1, GL_RGBA8, width, height);
|
|
glTextureSubImage2D(id, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
|
printf("[Texture %d, %s] Loaded successfully (%dx%d, %d channels)\n", id, path, width, height, channels);
|
|
} else {
|
|
glTextureParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTextureParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTextureParameteri(id, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTextureParameteri(id, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
glTextureStorage2D(id, 1, GL_RGBA8, width, height);
|
|
glTextureSubImage2D(id, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, default_texture);
|
|
printf("[Texture %d, %s] Failed to load image data: %s\n", id, path, stbi_failure_reason());
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
vec2 texture_quad_texcoords[] = {
|
|
{ 0.0f, 1.0f },
|
|
{ 0.0f, 0.0f },
|
|
{ 1.0f, 0.0f },
|
|
|
|
{ 0.0f, 1.0f },
|
|
{ 1.0f, 0.0f },
|
|
{ 1.0f, 1.0f }
|
|
};
|
|
|
|
void draw_texture(Texture id, vec2 pos, vec2 size, vec4 tint) {
|
|
mat4 transform = mat4Multiply(
|
|
mat4Scale(size.x, size.y, 1.0f),
|
|
mat4Translate(pos.x, pos.y, 0.0f));
|
|
|
|
draw_texture_trans(id, transform, tint);
|
|
}
|
|
|
|
void draw_texture_trans(Texture id, mat4 transform, vec4 tint) {
|
|
assert(texture_quad_batch != NULL && "texture_quad_batch is null, was setup_textures() called?");
|
|
batch_draw_texture(texture_quad_batch, id, transform, tint);
|
|
}
|
|
|
|
void batch_draw_texture(RenderBatch* batch, Texture texture, mat4 transform, vec4 color) {
|
|
TextureQuadBatchData* batch_data = (TextureQuadBatchData*)batch->data;
|
|
uint32_t vertex_add = 6;
|
|
|
|
if(batch_needs_flush(batch, vertex_add) || batch_data->texture_index >= max_textures)
|
|
flush_batch(batch);
|
|
|
|
uint32_t tex_id = batch_data->texture_index++;
|
|
glBindTextureUnit(tex_id, texture);
|
|
|
|
for(int i = 0; i < vertex_add; i++) {
|
|
TextureQuadVertex* vertex = (TextureQuadVertex*)batch->vertex_ptr;
|
|
|
|
vertex->Position = vec3Transform(quad_vertex_positions[i], transform);
|
|
vertex->Tint = color;
|
|
vertex->TexCoord = texture_quad_texcoords[i];
|
|
vertex->TexID = tex_id;
|
|
|
|
batch->vertex_ptr = (TextureQuadVertex*)batch->vertex_ptr + 1;
|
|
batch->vertex_count++;
|
|
}
|
|
}
|
|
|
|
void texture_flush_callback(RenderBatch* batch) {
|
|
TextureQuadBatchData* data = (TextureQuadBatchData*)batch->data;
|
|
data->texture_index = 0;
|
|
}
|
|
|
|
RenderBatch* create_texture_quad_batch() {
|
|
RenderBatch* texture_quad_batch = create_batch(sizeof(TextureQuadVertex), MAX_VERTICES);
|
|
texture_quad_batch->shader = load_shader_program(
|
|
compile_shader("assets/texture.vert", GL_VERTEX_SHADER),
|
|
compile_shader("assets/texture.frag", GL_FRAGMENT_SHADER), 0);
|
|
|
|
texture_quad_batch->data = new TextureQuadBatchData();
|
|
texture_quad_batch->flush_callback = &texture_flush_callback;
|
|
|
|
batch_add_attrib(texture_quad_batch, (VertexAttrib){
|
|
.type = GL_FLOAT, .size = sizeof(float), .count = 3
|
|
}); // pos
|
|
|
|
batch_add_attrib(texture_quad_batch, (VertexAttrib){
|
|
.type = GL_FLOAT, .size = sizeof(float), .count = 4
|
|
}); // color
|
|
|
|
batch_add_attrib(texture_quad_batch, (VertexAttrib){
|
|
.type = GL_FLOAT, .size = sizeof(float), .count = 2
|
|
}); // texcoord
|
|
|
|
batch_add_attrib(texture_quad_batch, (VertexAttrib){
|
|
.type = GL_FLOAT, .size = sizeof(float), .count = 1
|
|
}); // texid
|
|
|
|
batch_bind_attribs(texture_quad_batch);
|
|
|
|
return texture_quad_batch;
|
|
}
|