| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- #include "texture_renderer.h"
- #include <spdlog/spdlog.h>
- #include <cassert>
- #include <cstddef>
- static constexpr auto vertex_shader_source = R"(
- #version 460
- layout (location = 0) in vec2 pos_in;
- layout (location = 1) in vec2 tex_coord_in;
- out vec2 tex_coord;
- void main() {
- gl_Position = vec4(pos_in, 0, 1);
- tex_coord = tex_coord_in;
- }
- )";
- static constexpr auto fragment_shader_source = R"(
- #version 460
- layout (location = 0) out vec4 color_out;
- in vec2 tex_coord;
- uniform sampler2D tex_sampler;
- void main() {
- color_out = texture(tex_sampler, tex_coord);
- }
- )";
- static constexpr GLuint indices[] = {
- 0, 1, 3, // first triangle
- 1, 2, 3 // second triangle
- };
- struct texture_renderer::impl {
- GLuint vertex_array = 0;
- GLuint vertex_buffer = 0, element_buffer = 0;
- GLuint program = 0;
- impl() {
- // build program
- auto vertex_shader = glCreateShader(GL_VERTEX_SHADER);
- auto fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
- compile_shader(vertex_shader, vertex_shader_source, "vertex");
- compile_shader(fragment_shader, fragment_shader_source, "fragment");
- program = glCreateProgram();
- glAttachShader(program, vertex_shader);
- glAttachShader(program, fragment_shader);
- glLinkProgram(program);
- check_program();
- glDeleteShader(vertex_shader);
- glDeleteShader(fragment_shader);
- // create buffers
- static_assert(offsetof(impl, element_buffer) - offsetof(impl, vertex_buffer) == sizeof(GLuint));
- glGenBuffers(2, &vertex_buffer);
- // config vertex buffer
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
- glBufferStorage(GL_ARRAY_BUFFER, 16 * sizeof(GLfloat), nullptr, GL_DYNAMIC_STORAGE_BIT);
- // fill element buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
- // config vertex array
- glGenVertexArrays(1, &vertex_array);
- glBindVertexArray(vertex_array);
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
- glVertexAttribPointer(0, 2, GL_FLOAT, false, 4 * sizeof(GLfloat), (void *) 0);
- glVertexAttribPointer(1, 2, GL_FLOAT, false, 4 * sizeof(GLfloat), (void *) (2 * sizeof(GLfloat)));
- }
- ~impl() {
- glDeleteBuffers(2, &vertex_buffer);
- glDeleteProgram(program);
- }
- static void compile_shader(GLuint shader, const char *source, const char *name) {
- glShaderSource(shader, 1, &source, nullptr);
- glCompileShader(shader);
- GLint status, log_length;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
- glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
- auto info_log = (GLchar *) malloc(log_length);
- glGetShaderInfoLog(shader, log_length, nullptr, info_log);
- if (status == GL_TRUE) {
- SPDLOG_INFO("Compile {} shader succeeded: {}", name, info_log);
- } else {
- SPDLOG_ERROR("Compile {} shader failed: {}", name, info_log);
- assert(false);
- }
- free(info_log);
- }
- void check_program() {
- GLint status, log_length;
- glGetProgramiv(program, GL_LINK_STATUS, &status);
- glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
- auto info_log = (GLchar *) malloc(log_length);
- glGetProgramInfoLog(program, log_length, nullptr, info_log);
- if (status == GL_TRUE) {
- SPDLOG_INFO("Link program succeeded: {}", info_log);
- } else {
- SPDLOG_ERROR("Link program failed: {}", info_log);
- assert(false);
- }
- free(info_log);
- }
- void render(const texture_renderer::render_config *config) {
- auto x = config->x, y = config->y;
- auto width = config->width, height = config->height;
- // bindings
- glUseProgram(program);
- glBindVertexArray(vertex_array);
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer);
- glBindTexture(GL_TEXTURE_2D, config->tex);
- // fill vertex buffer
- GLfloat vertices[] = {
- // 2 for position; 2 for texture
- x + width, y + height, 1, 1, // top right
- x + width, y, 1, 0, // bottom right
- x, y, 0, 0, // bottom left
- x, y + height, 0, 1 // top left
- };
- static_assert(sizeof(vertices) == 16 * sizeof(GLfloat));
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
- // draw texture
- glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
- }
- };
- texture_renderer::texture_renderer()
- : pimpl(std::make_unique<impl>()) {}
- texture_renderer::~texture_renderer() = default;
- void texture_renderer::render(const texture_renderer::render_config *config) {
- pimpl->render(config);
- }
|