mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
milek7/sim branch opengl 3.3 renderer import
This commit is contained in:
27
gl/bindable.h
Normal file
27
gl/bindable.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
namespace gl
|
||||
{
|
||||
template <typename T>
|
||||
class bindable
|
||||
{
|
||||
protected:
|
||||
thread_local static bindable<T>* active;
|
||||
|
||||
public:
|
||||
void bind()
|
||||
{
|
||||
if (active == this)
|
||||
return;
|
||||
active = this;
|
||||
T::bind(*static_cast<T*>(active));
|
||||
}
|
||||
static void unbind()
|
||||
{
|
||||
active = nullptr;
|
||||
T::bind(0);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> thread_local bindable<T>* bindable<T>::active;
|
||||
}
|
||||
89
gl/buffer.cpp
Normal file
89
gl/buffer.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "stdafx.h"
|
||||
#include "buffer.h"
|
||||
|
||||
GLenum gl::buffer::glenum_target(gl::buffer::targets target)
|
||||
{
|
||||
static GLenum mapping[13] =
|
||||
{
|
||||
GL_ARRAY_BUFFER,
|
||||
GL_ATOMIC_COUNTER_BUFFER,
|
||||
GL_COPY_READ_BUFFER,
|
||||
GL_COPY_WRITE_BUFFER,
|
||||
GL_DISPATCH_INDIRECT_BUFFER,
|
||||
GL_DRAW_INDIRECT_BUFFER,
|
||||
GL_ELEMENT_ARRAY_BUFFER,
|
||||
GL_PIXEL_PACK_BUFFER,
|
||||
GL_PIXEL_UNPACK_BUFFER,
|
||||
GL_SHADER_STORAGE_BUFFER,
|
||||
GL_TEXTURE_BUFFER,
|
||||
GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
GL_UNIFORM_BUFFER
|
||||
};
|
||||
return mapping[target];
|
||||
}
|
||||
|
||||
void gl::buffer::bind(targets target)
|
||||
{
|
||||
if (binding_points[target] == *this)
|
||||
return;
|
||||
|
||||
glBindBuffer(glenum_target(target), *this);
|
||||
binding_points[target] = *this;
|
||||
}
|
||||
|
||||
void gl::buffer::bind_base(targets target, GLuint index)
|
||||
{
|
||||
glBindBufferBase(glenum_target(target), index, *this);
|
||||
binding_points[target] = *this;
|
||||
}
|
||||
|
||||
void gl::buffer::unbind(targets target)
|
||||
{
|
||||
glBindBuffer(glenum_target(target), 0);
|
||||
binding_points[target] = 0;
|
||||
}
|
||||
|
||||
void gl::buffer::unbind()
|
||||
{
|
||||
for (size_t i = 0; i < sizeof(binding_points) / sizeof(GLuint); i++)
|
||||
unbind((targets)i);
|
||||
}
|
||||
|
||||
gl::buffer::buffer()
|
||||
{
|
||||
glGenBuffers(1, *this);
|
||||
}
|
||||
|
||||
gl::buffer::~buffer()
|
||||
{
|
||||
glDeleteBuffers(1, *this);
|
||||
}
|
||||
|
||||
void gl::buffer::allocate(targets target, int size, GLenum hint)
|
||||
{
|
||||
bind(target);
|
||||
glBufferData(glenum_target(target), size, nullptr, hint);
|
||||
}
|
||||
|
||||
void gl::buffer::upload(targets target, const void *data, int offset, int size)
|
||||
{
|
||||
bind(target);
|
||||
glBufferSubData(glenum_target(target), offset, size, data);
|
||||
}
|
||||
|
||||
void gl::buffer::download(targets target, void *data, int offset, int size)
|
||||
{
|
||||
bind(target);
|
||||
if (GLAD_GL_VERSION_3_3)
|
||||
{
|
||||
glGetBufferSubData(glenum_target(target), offset, size, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
void *glbuf = glMapBufferRange(glenum_target(target), offset, size, GL_MAP_READ_BIT);
|
||||
memcpy(data, glbuf, size);
|
||||
glUnmapBuffer(glenum_target(target));
|
||||
}
|
||||
}
|
||||
|
||||
thread_local GLuint gl::buffer::binding_points[13];
|
||||
46
gl/buffer.h
Normal file
46
gl/buffer.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "object.h"
|
||||
#include "bindable.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
class buffer : public object
|
||||
{
|
||||
thread_local static GLuint binding_points[13];
|
||||
|
||||
public:
|
||||
enum targets
|
||||
{
|
||||
ARRAY_BUFFER = 0,
|
||||
ATOMIC_COUNTER_BUFFER,
|
||||
COPY_READ_BUFFER,
|
||||
COPY_WRITE_BUFFER,
|
||||
DISPATCH_INDIRECT_BUFFER,
|
||||
DRAW_INDIRECT_BUFFER,
|
||||
ELEMENT_ARRAY_BUFFER,
|
||||
PIXEL_PACK_BUFFER,
|
||||
PIXEL_UNPACK_BUFFER,
|
||||
SHADER_STORAGE_BUFFER,
|
||||
TEXTURE_BUFFER,
|
||||
TRANSFORM_FEEDBACK_BUFFER,
|
||||
UNIFORM_BUFFER
|
||||
};
|
||||
|
||||
protected:
|
||||
static GLenum glenum_target(targets target);
|
||||
|
||||
public:
|
||||
buffer();
|
||||
~buffer();
|
||||
|
||||
void bind(targets target);
|
||||
void bind_base(targets target, GLuint index);
|
||||
static void unbind(targets target);
|
||||
static void unbind();
|
||||
|
||||
void allocate(targets target, int size, GLenum hint);
|
||||
void upload(targets target, const void *data, int offset, int size);
|
||||
void download(targets target, void *data, int offset, int size);
|
||||
};
|
||||
}
|
||||
38
gl/cubemap.cpp
Normal file
38
gl/cubemap.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "stdafx.h"
|
||||
#include "cubemap.h"
|
||||
|
||||
gl::cubemap::cubemap()
|
||||
{
|
||||
glGenTextures(1, *this);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
gl::cubemap::~cubemap()
|
||||
{
|
||||
glDeleteTextures(1, *this);
|
||||
}
|
||||
|
||||
void gl::cubemap::alloc(GLint format, int width, int height, GLenum components, GLenum type)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, *this);
|
||||
for (GLuint tgt = GL_TEXTURE_CUBE_MAP_POSITIVE_X; tgt <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; tgt++)
|
||||
glTexImage2D(tgt, 0, format, width, height, 0, components, type, nullptr);
|
||||
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
}
|
||||
|
||||
void gl::cubemap::bind(int unit)
|
||||
{
|
||||
glActiveTexture(unit);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, *this);
|
||||
}
|
||||
|
||||
void gl::cubemap::generate_mipmaps()
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, *this);
|
||||
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
}
|
||||
19
gl/cubemap.h
Normal file
19
gl/cubemap.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "object.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
// cubemap texture rendertarget
|
||||
// todo: integrate with texture system
|
||||
class cubemap : public object
|
||||
{
|
||||
public:
|
||||
cubemap();
|
||||
~cubemap();
|
||||
|
||||
void alloc(GLint format, int width, int height, GLenum components, GLenum type);
|
||||
void bind(int unit);
|
||||
void generate_mipmaps();
|
||||
};
|
||||
}
|
||||
20
gl/fence.cpp
Normal file
20
gl/fence.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "stdafx.h"
|
||||
#include "fence.h"
|
||||
|
||||
gl::fence::fence()
|
||||
{
|
||||
sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
}
|
||||
|
||||
gl::fence::~fence()
|
||||
{
|
||||
glDeleteSync(sync);
|
||||
}
|
||||
|
||||
bool gl::fence::is_signalled()
|
||||
{
|
||||
GLsizei len = 0;
|
||||
GLint val;
|
||||
glGetSynciv(sync, GL_SYNC_STATUS, 1, &len, &val);
|
||||
return len == 1 && val == GL_SIGNALED;
|
||||
}
|
||||
20
gl/fence.h
Normal file
20
gl/fence.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "object.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
class fence
|
||||
{
|
||||
GLsync sync;
|
||||
|
||||
public:
|
||||
fence();
|
||||
~fence();
|
||||
|
||||
bool is_signalled();
|
||||
|
||||
fence(const fence&) = delete;
|
||||
fence& operator=(const fence&) = delete;
|
||||
};
|
||||
}
|
||||
103
gl/framebuffer.cpp
Normal file
103
gl/framebuffer.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
#include "stdafx.h"
|
||||
#include "framebuffer.h"
|
||||
|
||||
gl::framebuffer::framebuffer()
|
||||
{
|
||||
glGenFramebuffers(1, *this);
|
||||
}
|
||||
|
||||
gl::framebuffer::~framebuffer()
|
||||
{
|
||||
glDeleteFramebuffers(1, *this);
|
||||
}
|
||||
|
||||
void gl::framebuffer::bind(GLuint id)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, id);
|
||||
}
|
||||
|
||||
void gl::framebuffer::attach(const opengl_texture &tex, GLenum location)
|
||||
{
|
||||
bind();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, location, tex.target, tex.id, 0);
|
||||
}
|
||||
|
||||
void gl::framebuffer::attach(const cubemap &tex, int face, GLenum location)
|
||||
{
|
||||
bind();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, location, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, *tex, 0);
|
||||
}
|
||||
|
||||
void gl::framebuffer::attach(const renderbuffer &rb, GLenum location)
|
||||
{
|
||||
bind();
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, location, GL_RENDERBUFFER, *rb);
|
||||
}
|
||||
|
||||
void gl::framebuffer::detach(GLenum location)
|
||||
{
|
||||
bind();
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, location, GL_RENDERBUFFER, 0);
|
||||
}
|
||||
|
||||
bool gl::framebuffer::is_complete()
|
||||
{
|
||||
bind();
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
return status == GL_FRAMEBUFFER_COMPLETE;
|
||||
}
|
||||
|
||||
void gl::framebuffer::clear(GLbitfield mask)
|
||||
{
|
||||
bind();
|
||||
if (mask & GL_DEPTH_BUFFER_BIT)
|
||||
glDepthMask(GL_TRUE);
|
||||
glClear(mask);
|
||||
}
|
||||
|
||||
void gl::framebuffer::blit_to(framebuffer *other, int w, int h, GLbitfield mask, GLenum attachment)
|
||||
{
|
||||
blit(this, other, 0, 0, w, h, mask, attachment);
|
||||
}
|
||||
|
||||
void gl::framebuffer::blit_from(framebuffer *other, int w, int h, GLbitfield mask, GLenum attachment)
|
||||
{
|
||||
blit(other, this, 0, 0, w, h, mask, attachment);
|
||||
}
|
||||
|
||||
void gl::framebuffer::blit(framebuffer *src, framebuffer *dst, int sx, int sy, int w, int h, GLbitfield mask, GLenum attachment)
|
||||
{
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, src ? *src : 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst ? *dst : 0);
|
||||
|
||||
if (mask & GL_COLOR_BUFFER_BIT)
|
||||
{
|
||||
int attachment_n = attachment - GL_COLOR_ATTACHMENT0;
|
||||
|
||||
GLenum outputs[8] = { GL_NONE };
|
||||
outputs[attachment_n] = attachment;
|
||||
|
||||
glReadBuffer(attachment);
|
||||
glDrawBuffers(attachment_n + 1, outputs);
|
||||
}
|
||||
|
||||
glBlitFramebuffer(sx, sy, sx + w, sy + h, 0, 0, w, h, mask, GL_NEAREST);
|
||||
unbind();
|
||||
}
|
||||
|
||||
void gl::framebuffer::setup_drawing(int attachments)
|
||||
{
|
||||
bind();
|
||||
GLenum a[8] =
|
||||
{
|
||||
GL_COLOR_ATTACHMENT0,
|
||||
GL_COLOR_ATTACHMENT1,
|
||||
GL_COLOR_ATTACHMENT2,
|
||||
GL_COLOR_ATTACHMENT3,
|
||||
GL_COLOR_ATTACHMENT4,
|
||||
GL_COLOR_ATTACHMENT5,
|
||||
GL_COLOR_ATTACHMENT6,
|
||||
GL_COLOR_ATTACHMENT7
|
||||
};
|
||||
glDrawBuffers(std::min(attachments, 8), &a[0]);
|
||||
}
|
||||
33
gl/framebuffer.h
Normal file
33
gl/framebuffer.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "object.h"
|
||||
#include "bindable.h"
|
||||
#include "renderbuffer.h"
|
||||
#include "Texture.h"
|
||||
#include "cubemap.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
class framebuffer : public object, public bindable<framebuffer>
|
||||
{
|
||||
public:
|
||||
framebuffer();
|
||||
~framebuffer();
|
||||
|
||||
void attach(const opengl_texture &tex, GLenum location);
|
||||
void attach(const cubemap &tex, int face, GLenum location);
|
||||
void attach(const renderbuffer &rb, GLenum location);
|
||||
void setup_drawing(int attachments);
|
||||
void detach(GLenum location);
|
||||
void clear(GLbitfield mask);
|
||||
|
||||
bool is_complete();
|
||||
void blit_to(framebuffer *other, int w, int h, GLbitfield mask, GLenum attachment);
|
||||
void blit_from(framebuffer *other, int w, int h, GLbitfield mask, GLenum attachment);
|
||||
|
||||
static void blit(framebuffer *src, framebuffer *dst, int sx, int sy, int w, int h, GLbitfield mask, GLenum attachment);
|
||||
|
||||
using bindable::bind;
|
||||
static void bind(GLuint id);
|
||||
};
|
||||
}
|
||||
72
gl/glsl_common.cpp
Normal file
72
gl/glsl_common.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "stdafx.h"
|
||||
#include "glsl_common.h"
|
||||
|
||||
std::string gl::glsl_common;
|
||||
|
||||
void gl::glsl_common_setup()
|
||||
{
|
||||
glsl_common =
|
||||
"#define SHADOWMAP_ENABLED " + std::to_string((int)Global.gfx_shadowmap_enabled) + "\n" +
|
||||
"#define ENVMAP_ENABLED " + std::to_string((int)Global.gfx_envmap_enabled) + "\n" +
|
||||
"#define MOTIONBLUR_ENABLED " + std::to_string((int)Global.gfx_postfx_motionblur_enabled) + "\n" +
|
||||
"#define POSTFX_ENABLED " + std::to_string((int)!Global.gfx_skippipeline) + "\n" +
|
||||
"#define EXTRAEFFECTS_ENABLED " + std::to_string((int)Global.gfx_extraeffects) + "\n" +
|
||||
"#define USE_GLES " + std::to_string((int)Global.gfx_usegles) + "\n" +
|
||||
"const uint MAX_LIGHTS = " + std::to_string(MAX_LIGHTS) + "U;\n" +
|
||||
"const uint MAX_PARAMS = " + std::to_string(MAX_PARAMS) + "U;\n" +
|
||||
R"STRING(
|
||||
const uint LIGHT_SPOT = 0U;
|
||||
const uint LIGHT_POINT = 1U;
|
||||
const uint LIGHT_DIR = 2U;
|
||||
|
||||
struct light_s
|
||||
{
|
||||
vec3 pos;
|
||||
uint type;
|
||||
|
||||
vec3 dir;
|
||||
float in_cutoff;
|
||||
|
||||
vec3 color;
|
||||
float out_cutoff;
|
||||
|
||||
float linear;
|
||||
float quadratic;
|
||||
|
||||
float intensity;
|
||||
float ambient;
|
||||
};
|
||||
|
||||
layout(std140) uniform light_ubo
|
||||
{
|
||||
vec3 ambient;
|
||||
|
||||
vec3 fog_color;
|
||||
uint lights_count;
|
||||
|
||||
light_s lights[MAX_LIGHTS];
|
||||
};
|
||||
|
||||
layout (std140) uniform model_ubo
|
||||
{
|
||||
mat4 modelview;
|
||||
mat3 modelviewnormal;
|
||||
vec4 param[MAX_PARAMS];
|
||||
|
||||
mat4 future;
|
||||
float opacity;
|
||||
float emission;
|
||||
float fog_density;
|
||||
float alpha_mult;
|
||||
};
|
||||
|
||||
layout (std140) uniform scene_ubo
|
||||
{
|
||||
mat4 projection;
|
||||
mat4 lightview;
|
||||
vec3 scene_extra;
|
||||
float time;
|
||||
};
|
||||
|
||||
)STRING";
|
||||
}
|
||||
10
gl/glsl_common.h
Normal file
10
gl/glsl_common.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "ubo.h"
|
||||
#include "Globals.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
extern std::string glsl_common;
|
||||
void glsl_common_setup();
|
||||
}
|
||||
32
gl/object.h
Normal file
32
gl/object.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <glad/glad.h>
|
||||
|
||||
namespace gl
|
||||
{
|
||||
class object
|
||||
{
|
||||
private:
|
||||
GLuint id = 0;
|
||||
|
||||
public:
|
||||
inline operator GLuint() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
inline operator GLuint* const()
|
||||
{
|
||||
return &id;
|
||||
}
|
||||
|
||||
inline operator const GLuint* const() const
|
||||
{
|
||||
return &id;
|
||||
}
|
||||
|
||||
object() = default;
|
||||
object(const object&) = delete;
|
||||
object& operator=(const object&) = delete;
|
||||
};
|
||||
}
|
||||
65
gl/pbo.cpp
Normal file
65
gl/pbo.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "stdafx.h"
|
||||
#include "pbo.h"
|
||||
|
||||
void gl::pbo::request_read(int x, int y, int lx, int ly, int pixsize, GLenum format, GLenum type)
|
||||
{
|
||||
int s = lx * ly * pixsize;
|
||||
if (s != size)
|
||||
allocate(PIXEL_PACK_BUFFER, s, GL_STREAM_DRAW);
|
||||
size = s;
|
||||
|
||||
data_ready = false;
|
||||
sync.reset();
|
||||
|
||||
bind(PIXEL_PACK_BUFFER);
|
||||
glReadPixels(x, y, lx, ly, format, type, 0);
|
||||
unbind(PIXEL_PACK_BUFFER);
|
||||
|
||||
sync.emplace();
|
||||
}
|
||||
|
||||
bool gl::pbo::read_data(int lx, int ly, void *data, int pixsize)
|
||||
{
|
||||
is_busy();
|
||||
|
||||
if (!data_ready)
|
||||
return false;
|
||||
|
||||
int s = lx * ly * pixsize;
|
||||
if (s != size)
|
||||
return false;
|
||||
|
||||
download(PIXEL_PACK_BUFFER, data, 0, s);
|
||||
unbind(PIXEL_PACK_BUFFER);
|
||||
data_ready = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gl::pbo::is_busy()
|
||||
{
|
||||
if (!sync)
|
||||
return false;
|
||||
|
||||
if (sync->is_signalled())
|
||||
{
|
||||
data_ready = true;
|
||||
sync.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void* gl::pbo::map(GLuint mode, targets target)
|
||||
{
|
||||
bind(target);
|
||||
return glMapBuffer(buffer::glenum_target(target), mode);
|
||||
}
|
||||
|
||||
void gl::pbo::unmap(targets target)
|
||||
{
|
||||
bind(target);
|
||||
glUnmapBuffer(buffer::glenum_target(target));
|
||||
sync.emplace();
|
||||
}
|
||||
22
gl/pbo.h
Normal file
22
gl/pbo.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "buffer.h"
|
||||
#include "fence.h"
|
||||
#include <optional>
|
||||
|
||||
namespace gl {
|
||||
class pbo : public buffer
|
||||
{
|
||||
std::optional<fence> sync;
|
||||
int size = 0;
|
||||
bool data_ready;
|
||||
|
||||
public:
|
||||
void request_read(int x, int y, int lx, int ly, int pixsize = 4, GLenum format = GL_RGBA, GLenum type = GL_UNSIGNED_BYTE);
|
||||
bool read_data(int lx, int ly, void *data, int pixsize = 4);
|
||||
bool is_busy();
|
||||
|
||||
void* map(GLuint mode, targets target = PIXEL_UNPACK_BUFFER);
|
||||
void unmap(targets target = PIXEL_UNPACK_BUFFER);
|
||||
};
|
||||
}
|
||||
49
gl/postfx.cpp
Normal file
49
gl/postfx.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "postfx.h"
|
||||
|
||||
std::shared_ptr<gl::shader> gl::postfx::vertex;
|
||||
std::shared_ptr<gl::vao> gl::postfx::vao;
|
||||
|
||||
gl::postfx::postfx(const std::string &s) : postfx(shader("postfx_" + s + ".frag"))
|
||||
{
|
||||
}
|
||||
|
||||
gl::postfx::postfx(const shader &s)
|
||||
{
|
||||
if (!vertex)
|
||||
vertex = std::make_shared<gl::shader>("quad.vert");
|
||||
if (!vao)
|
||||
vao = std::make_shared<gl::vao>();
|
||||
|
||||
program.attach(*vertex);
|
||||
program.attach(s);
|
||||
program.link();
|
||||
}
|
||||
|
||||
void gl::postfx::apply(opengl_texture &src, framebuffer *dst)
|
||||
{
|
||||
apply({&src}, dst);
|
||||
}
|
||||
|
||||
void gl::postfx::apply(std::vector<opengl_texture *> src, framebuffer *dst)
|
||||
{
|
||||
if (dst)
|
||||
{
|
||||
dst->clear(GL_COLOR_BUFFER_BIT);
|
||||
dst->bind();
|
||||
}
|
||||
else
|
||||
framebuffer::unbind();
|
||||
|
||||
program.bind();
|
||||
vao->bind();
|
||||
|
||||
size_t unit = 0;
|
||||
for (opengl_texture *tex : src)
|
||||
tex->bind(unit++);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
25
gl/postfx.h
Normal file
25
gl/postfx.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "shader.h"
|
||||
#include "vao.h"
|
||||
#include "framebuffer.h"
|
||||
#include "Texture.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
class postfx
|
||||
{
|
||||
private:
|
||||
gl::program program;
|
||||
static std::shared_ptr<gl::shader> vertex;
|
||||
static std::shared_ptr<gl::vao> vao;
|
||||
|
||||
public:
|
||||
postfx(const std::string &s);
|
||||
postfx(const shader &s);
|
||||
|
||||
void attach();
|
||||
void apply(opengl_texture &src, framebuffer *dst);
|
||||
void apply(std::vector<opengl_texture*> src, framebuffer *dst);
|
||||
};
|
||||
}
|
||||
65
gl/query.cpp
Normal file
65
gl/query.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "stdafx.h"
|
||||
#include "query.h"
|
||||
#include "Globals.h"
|
||||
|
||||
gl::query::query(targets target)
|
||||
: target(target)
|
||||
{
|
||||
glGenQueries(1, *this);
|
||||
}
|
||||
|
||||
gl::query::~query()
|
||||
{
|
||||
end();
|
||||
glDeleteQueries(1, *this);
|
||||
}
|
||||
|
||||
void gl::query::begin()
|
||||
{
|
||||
if (active_queries[target])
|
||||
active_queries[target]->end();
|
||||
|
||||
glBeginQuery(glenum_target(target), *this);
|
||||
active_queries[target] = this;
|
||||
}
|
||||
|
||||
void gl::query::end()
|
||||
{
|
||||
if (active_queries[target] != this)
|
||||
return;
|
||||
|
||||
glEndQuery(glenum_target(target));
|
||||
active_queries[target] = nullptr;
|
||||
}
|
||||
|
||||
std::optional<int64_t> gl::query::result()
|
||||
{
|
||||
GLuint ready;
|
||||
glGetQueryObjectuiv(*this, GL_QUERY_RESULT_AVAILABLE, &ready);
|
||||
int64_t value = 0;
|
||||
if (ready) {
|
||||
if (!Global.gfx_usegles)
|
||||
glGetQueryObjecti64v(*this, GL_QUERY_RESULT, &value);
|
||||
else
|
||||
glGetQueryObjectuiv(*this, GL_QUERY_RESULT, reinterpret_cast<GLuint*>(&value));
|
||||
|
||||
return std::optional<int64_t>(value);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
GLenum gl::query::glenum_target(targets target)
|
||||
{
|
||||
static GLenum mapping[6] =
|
||||
{
|
||||
GL_SAMPLES_PASSED,
|
||||
GL_ANY_SAMPLES_PASSED,
|
||||
GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
|
||||
GL_PRIMITIVES_GENERATED,
|
||||
GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN,
|
||||
GL_TIME_ELAPSED
|
||||
};
|
||||
return mapping[target];
|
||||
}
|
||||
|
||||
thread_local gl::query* gl::query::active_queries[6];
|
||||
36
gl/query.h
Normal file
36
gl/query.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "object.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
class query : public object
|
||||
{
|
||||
public:
|
||||
enum targets
|
||||
{
|
||||
SAMPLES_PASSED = 0,
|
||||
ANY_SAMPLES_PASSED,
|
||||
ANY_SAMPLES_PASSED_CONSERVATIVE,
|
||||
PRIMITIVES_GENERATED,
|
||||
TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN,
|
||||
TIME_ELAPSED
|
||||
};
|
||||
|
||||
private:
|
||||
targets target;
|
||||
thread_local static query* active_queries[6];
|
||||
|
||||
protected:
|
||||
GLenum glenum_target(targets target);
|
||||
|
||||
public:
|
||||
query(targets target);
|
||||
~query();
|
||||
|
||||
void begin();
|
||||
void end();
|
||||
|
||||
std::optional<int64_t> result();
|
||||
};
|
||||
}
|
||||
27
gl/renderbuffer.cpp
Normal file
27
gl/renderbuffer.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "renderbuffer.h"
|
||||
|
||||
gl::renderbuffer::renderbuffer()
|
||||
{
|
||||
glGenRenderbuffers(1, *this);
|
||||
}
|
||||
|
||||
gl::renderbuffer::~renderbuffer()
|
||||
{
|
||||
glDeleteRenderbuffers(1, *this);
|
||||
}
|
||||
|
||||
void gl::renderbuffer::bind(GLuint id)
|
||||
{
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, id);
|
||||
}
|
||||
|
||||
void gl::renderbuffer::alloc(GLuint format, int width, int height, int samples)
|
||||
{
|
||||
bind();
|
||||
if (samples == 1)
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
|
||||
else
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, format, width, height);
|
||||
}
|
||||
19
gl/renderbuffer.h
Normal file
19
gl/renderbuffer.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "object.h"
|
||||
#include "bindable.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
class renderbuffer : public object, public bindable<renderbuffer>
|
||||
{
|
||||
public:
|
||||
renderbuffer();
|
||||
~renderbuffer();
|
||||
|
||||
void alloc(GLuint format, int width, int height, int samples = 1);
|
||||
|
||||
static void bind(GLuint id);
|
||||
using bindable::bind;
|
||||
};
|
||||
}
|
||||
334
gl/shader.cpp
Normal file
334
gl/shader.cpp
Normal file
@@ -0,0 +1,334 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include "shader.h"
|
||||
#include "glsl_common.h"
|
||||
#include "Logs.h"
|
||||
|
||||
inline bool strcend(std::string const &value, std::string const &ending)
|
||||
{
|
||||
if (ending.size() > value.size())
|
||||
return false;
|
||||
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
||||
}
|
||||
|
||||
std::string gl::shader::read_file(const std::string &filename)
|
||||
{
|
||||
std::stringstream stream;
|
||||
std::ifstream f;
|
||||
f.exceptions(std::ifstream::badbit);
|
||||
|
||||
f.open("shaders/" + filename);
|
||||
stream << f.rdbuf();
|
||||
f.close();
|
||||
|
||||
std::string str = stream.str();
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void gl::shader::expand_includes(std::string &str)
|
||||
{
|
||||
size_t start_pos = 0;
|
||||
|
||||
std::string magic = "#include";
|
||||
while ((start_pos = str.find(magic, start_pos)) != str.npos)
|
||||
{
|
||||
size_t fp = str.find('<', start_pos);
|
||||
size_t fe = str.find('>', start_pos);
|
||||
if (fp == str.npos || fe == str.npos)
|
||||
return;
|
||||
|
||||
std::string filename = str.substr(fp + 1, fe - fp - 1);
|
||||
std::string content;
|
||||
if (filename != "common")
|
||||
content = read_file(filename);
|
||||
else
|
||||
content = glsl_common;
|
||||
|
||||
str.replace(start_pos, fe - start_pos + 1, content);
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, gl::shader::components_e> gl::shader::components_mapping =
|
||||
{
|
||||
{ "R", components_e::R },
|
||||
{ "RG", components_e::RG },
|
||||
{ "RGB", components_e::RGB },
|
||||
{ "RGBA", components_e::RGBA },
|
||||
{ "sRGB", components_e::sRGB },
|
||||
{ "sRGB_A", components_e::sRGB_A }
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, gl::shader::defaultparam_e> gl::shader::defaultparams_mapping =
|
||||
{
|
||||
{ "required", defaultparam_e::required },
|
||||
{ "nan", defaultparam_e::nan },
|
||||
{ "zero", defaultparam_e::zero },
|
||||
{ "one", defaultparam_e::one },
|
||||
{ "ambient", defaultparam_e::ambient },
|
||||
{ "diffuse", defaultparam_e::diffuse },
|
||||
{ "specular", defaultparam_e::specular }
|
||||
};
|
||||
|
||||
void gl::shader::process_source(std::string &str)
|
||||
{
|
||||
expand_includes(str);
|
||||
parse_texture_entries(str);
|
||||
parse_param_entries(str);
|
||||
}
|
||||
|
||||
void gl::shader::parse_texture_entries(std::string &str)
|
||||
{
|
||||
size_t start_pos = 0;
|
||||
|
||||
std::string magic = "#texture";
|
||||
while ((start_pos = str.find(magic, start_pos)) != str.npos)
|
||||
{
|
||||
size_t fp = str.find('(', start_pos);
|
||||
size_t fe = str.find(')', start_pos);
|
||||
if (fp == str.npos || fe == str.npos)
|
||||
return;
|
||||
|
||||
std::istringstream ss(str.substr(fp + 1, fe - fp - 1));
|
||||
std::string token;
|
||||
|
||||
std::string name;
|
||||
texture_entry conf;
|
||||
|
||||
size_t arg = 0;
|
||||
while (std::getline(ss, token, ','))
|
||||
{
|
||||
std::istringstream token_ss(token);
|
||||
if (arg == 0)
|
||||
token_ss >> name;
|
||||
else if (arg == 1)
|
||||
token_ss >> conf.id;
|
||||
else if (arg == 2)
|
||||
{
|
||||
std::string comp;
|
||||
token_ss >> comp;
|
||||
if (components_mapping.find(comp) == components_mapping.end())
|
||||
log_error("unknown components: " + comp);
|
||||
else
|
||||
conf.components = components_mapping[comp];
|
||||
}
|
||||
arg++;
|
||||
}
|
||||
|
||||
if (arg == 3)
|
||||
{
|
||||
if (name.empty())
|
||||
log_error("empty name");
|
||||
else if (conf.id >= gl::MAX_TEXTURES)
|
||||
log_error("invalid texture binding: " + std::to_string(conf.id));
|
||||
else
|
||||
texture_conf.emplace(std::make_pair(name, conf));
|
||||
}
|
||||
else
|
||||
log_error("invalid argument count to #texture");
|
||||
|
||||
str.erase(start_pos, fe - start_pos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void gl::shader::parse_param_entries(std::string &str)
|
||||
{
|
||||
size_t start_pos = 0;
|
||||
|
||||
std::string magic = "#param";
|
||||
while ((start_pos = str.find(magic, start_pos)) != str.npos)
|
||||
{
|
||||
size_t fp = str.find('(', start_pos);
|
||||
size_t fe = str.find(')', start_pos);
|
||||
if (fp == str.npos || fe == str.npos)
|
||||
return;
|
||||
|
||||
std::istringstream ss(str.substr(fp + 1, fe - fp - 1));
|
||||
std::string token;
|
||||
|
||||
std::string name;
|
||||
param_entry conf;
|
||||
|
||||
size_t arg = 0;
|
||||
while (std::getline(ss, token, ','))
|
||||
{
|
||||
std::istringstream token_ss(token);
|
||||
if (arg == 0)
|
||||
token_ss >> name;
|
||||
else if (arg == 1)
|
||||
token_ss >> conf.location;
|
||||
else if (arg == 2)
|
||||
token_ss >> conf.offset;
|
||||
else if (arg == 3)
|
||||
token_ss >> conf.size;
|
||||
else if (arg == 4)
|
||||
{
|
||||
std::string tok;
|
||||
token_ss >> tok;
|
||||
if (defaultparams_mapping.find(tok) == defaultparams_mapping.end())
|
||||
log_error("unknown param default: " + tok);
|
||||
conf.defaultparam = defaultparams_mapping[tok];
|
||||
}
|
||||
arg++;
|
||||
}
|
||||
|
||||
if (arg == 5)
|
||||
{
|
||||
if (name.empty())
|
||||
log_error("empty name");
|
||||
else if (conf.location >= gl::MAX_PARAMS)
|
||||
log_error("invalid param binding: " + std::to_string(conf.location));
|
||||
else if (conf.offset > 3)
|
||||
log_error("invalid offset: " + std::to_string(conf.offset));
|
||||
else if (conf.offset + conf.size > 4)
|
||||
log_error("invalid size: " + std::to_string(conf.size));
|
||||
else
|
||||
param_conf.emplace(std::make_pair(name, conf));
|
||||
}
|
||||
else
|
||||
log_error("invalid argument count to #param");
|
||||
|
||||
str.erase(start_pos, fe - start_pos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void gl::shader::log_error(const std::string &str)
|
||||
{
|
||||
ErrorLog("bad shader: " + name + ": " + str, logtype::shader);
|
||||
}
|
||||
|
||||
gl::shader::shader(const std::string &filename)
|
||||
{
|
||||
name = filename;
|
||||
|
||||
GLuint type;
|
||||
if (strcend(filename, ".vert"))
|
||||
type = GL_VERTEX_SHADER;
|
||||
else if (strcend(filename, ".frag"))
|
||||
type = GL_FRAGMENT_SHADER;
|
||||
else if (strcend(filename, ".geom"))
|
||||
type = GL_GEOMETRY_SHADER;
|
||||
else
|
||||
throw shader_exception("unknown shader " + filename);
|
||||
|
||||
std::string str;
|
||||
if (!Global.gfx_usegles)
|
||||
{
|
||||
str += "#version 330 core\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GLAD_GL_ES_VERSION_3_1) {
|
||||
str += "#version 310 es\n";
|
||||
if (type == GL_GEOMETRY_SHADER)
|
||||
str += "#extension GL_EXT_geometry_shader : require\n";
|
||||
} else {
|
||||
str += "#version 300 es\n";
|
||||
}
|
||||
str += "precision highp float;\n";
|
||||
str += "precision highp sampler2DShadow;\n";
|
||||
}
|
||||
str += "vec4 FBOUT(vec4 x) { return " + (Global.gfx_shadergamma ? std::string("vec4(pow(x.rgb, vec3(1.0 / 2.2)), x.a)") : std::string("x")) + "; }\n";
|
||||
|
||||
str += read_file(filename);
|
||||
process_source(str);
|
||||
|
||||
const GLchar *cstr = str.c_str();
|
||||
|
||||
if (!cstr[0])
|
||||
throw shader_exception("cannot read shader: " + filename);
|
||||
|
||||
**this = glCreateShader(type);
|
||||
glShaderSource(*this, 1, &cstr, 0);
|
||||
glCompileShader(*this);
|
||||
|
||||
GLint status;
|
||||
glGetShaderiv(*this, GL_COMPILE_STATUS, &status);
|
||||
if (!status)
|
||||
{
|
||||
GLchar info[512];
|
||||
glGetShaderInfoLog(*this, 512, 0, info);
|
||||
std::cerr << std::string(info) << std::endl;
|
||||
throw shader_exception("failed to compile " + filename + ": " + std::string(info));
|
||||
}
|
||||
}
|
||||
|
||||
gl::shader::~shader()
|
||||
{
|
||||
glDeleteShader(*this);
|
||||
}
|
||||
|
||||
void gl::program::init()
|
||||
{
|
||||
bind();
|
||||
|
||||
for (auto it : texture_conf)
|
||||
{
|
||||
shader::texture_entry &e = it.second;
|
||||
GLuint loc = glGetUniformLocation(*this, it.first.c_str());
|
||||
glUniform1i(loc, e.id);
|
||||
}
|
||||
|
||||
glUniform1i(glGetUniformLocation(*this, "shadowmap"), MAX_TEXTURES + 0);
|
||||
glUniform1i(glGetUniformLocation(*this, "envmap"), MAX_TEXTURES + 1);
|
||||
|
||||
GLuint index;
|
||||
|
||||
if ((index = glGetUniformBlockIndex(*this, "scene_ubo")) != GL_INVALID_INDEX)
|
||||
glUniformBlockBinding(*this, 0, index);
|
||||
|
||||
if ((index = glGetUniformBlockIndex(*this, "model_ubo")) != GL_INVALID_INDEX)
|
||||
glUniformBlockBinding(*this, 1, index);
|
||||
|
||||
if ((index = glGetUniformBlockIndex(*this, "light_ubo")) != GL_INVALID_INDEX)
|
||||
glUniformBlockBinding(*this, 2, index);
|
||||
}
|
||||
|
||||
gl::program::program()
|
||||
{
|
||||
**this = glCreateProgram();
|
||||
}
|
||||
|
||||
gl::program::program(std::vector<std::reference_wrapper<const gl::shader>> shaders) : program()
|
||||
{
|
||||
for (const gl::shader &s : shaders)
|
||||
attach(s);
|
||||
link();
|
||||
}
|
||||
|
||||
void gl::program::attach(const gl::shader &s)
|
||||
{
|
||||
for (auto it : s.texture_conf)
|
||||
texture_conf.emplace(std::make_pair(it.first, std::move(it.second)));
|
||||
for (auto it : s.param_conf)
|
||||
param_conf.emplace(std::make_pair(it.first, std::move(it.second)));
|
||||
glAttachShader(*this, *s);
|
||||
}
|
||||
|
||||
void gl::program::link()
|
||||
{
|
||||
glLinkProgram(*this);
|
||||
|
||||
GLint status;
|
||||
glGetProgramiv(*this, GL_LINK_STATUS, &status);
|
||||
if (!status)
|
||||
{
|
||||
GLchar info[512];
|
||||
glGetProgramInfoLog(*this, 512, 0, info);
|
||||
throw shader_exception("failed to link program: " + std::string(info));
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
gl::program::~program()
|
||||
{
|
||||
glDeleteProgram(*this);
|
||||
}
|
||||
|
||||
void gl::program::bind(GLuint i)
|
||||
{
|
||||
glUseProgram(i);
|
||||
}
|
||||
96
gl/shader.h
Normal file
96
gl/shader.h
Normal file
@@ -0,0 +1,96 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
#include "object.h"
|
||||
#include "bindable.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
class shader_exception : public std::runtime_error
|
||||
{
|
||||
using runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
class shader : public object
|
||||
{
|
||||
public:
|
||||
shader(const std::string &filename);
|
||||
~shader();
|
||||
|
||||
enum class components_e
|
||||
{
|
||||
R = GL_RED,
|
||||
RG = GL_RG,
|
||||
RGB = GL_RGB,
|
||||
RGBA = GL_RGBA,
|
||||
sRGB = GL_SRGB,
|
||||
sRGB_A = GL_SRGB_ALPHA
|
||||
};
|
||||
|
||||
struct texture_entry
|
||||
{
|
||||
size_t id;
|
||||
components_e components;
|
||||
};
|
||||
|
||||
enum class defaultparam_e
|
||||
{
|
||||
required,
|
||||
nan,
|
||||
zero,
|
||||
one,
|
||||
ambient,
|
||||
diffuse,
|
||||
specular
|
||||
};
|
||||
|
||||
struct param_entry
|
||||
{
|
||||
size_t location;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
defaultparam_e defaultparam;
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, texture_entry> texture_conf;
|
||||
std::unordered_map<std::string, param_entry> param_conf;
|
||||
std::string name;
|
||||
|
||||
private:
|
||||
void process_source(std::string &str);
|
||||
|
||||
void expand_includes(std::string &str);
|
||||
void parse_texture_entries(std::string &str);
|
||||
void parse_param_entries(std::string &str);
|
||||
|
||||
std::string read_file(const std::string &filename);
|
||||
|
||||
static std::unordered_map<std::string, components_e> components_mapping;
|
||||
static std::unordered_map<std::string, defaultparam_e> defaultparams_mapping;
|
||||
|
||||
void log_error(const std::string &str);
|
||||
};
|
||||
|
||||
class program : public object, public bindable<program>
|
||||
{
|
||||
public:
|
||||
program();
|
||||
program(std::vector<std::reference_wrapper<const gl::shader>>);
|
||||
~program();
|
||||
|
||||
using bindable::bind;
|
||||
static void bind(GLuint i);
|
||||
|
||||
void attach(const shader &);
|
||||
void link();
|
||||
|
||||
std::unordered_map<std::string, shader::texture_entry> texture_conf;
|
||||
std::unordered_map<std::string, shader::param_entry> param_conf;
|
||||
|
||||
private:
|
||||
void init();
|
||||
};
|
||||
}
|
||||
19
gl/ubo.cpp
Normal file
19
gl/ubo.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "stdafx.h"
|
||||
#include "ubo.h"
|
||||
|
||||
gl::ubo::ubo(int size, int idx, GLenum hint)
|
||||
{
|
||||
allocate(buffer::UNIFORM_BUFFER, size, hint);
|
||||
index = idx;
|
||||
bind_uniform();
|
||||
}
|
||||
|
||||
void gl::ubo::bind_uniform()
|
||||
{
|
||||
bind_base(buffer::UNIFORM_BUFFER, index);
|
||||
}
|
||||
|
||||
void gl::ubo::update(const uint8_t *data, int offset, int size)
|
||||
{
|
||||
upload(buffer::UNIFORM_BUFFER, data, offset, size);
|
||||
}
|
||||
113
gl/ubo.h
Normal file
113
gl/ubo.h
Normal file
@@ -0,0 +1,113 @@
|
||||
#pragma once
|
||||
|
||||
#include "object.h"
|
||||
#include "bindable.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#define UBS_PAD(x) uint8_t PAD[x]
|
||||
|
||||
namespace gl
|
||||
{
|
||||
class ubo : public buffer
|
||||
{
|
||||
int index;
|
||||
|
||||
public:
|
||||
ubo(int size, int index, GLenum hint = GL_DYNAMIC_DRAW);
|
||||
|
||||
void bind_uniform();
|
||||
|
||||
void update(const uint8_t *data, int offset, int size);
|
||||
template <typename T> void update(const T &data, size_t offset = 0)
|
||||
{
|
||||
update(reinterpret_cast<const uint8_t*>(&data), offset, sizeof(data));
|
||||
}
|
||||
};
|
||||
|
||||
// layout std140
|
||||
// structs must match with GLSL
|
||||
// ordered to minimize padding
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
const size_t MAX_TEXTURES = 8;
|
||||
const size_t ENVMAP_SIZE = 1024;
|
||||
|
||||
struct scene_ubs
|
||||
{
|
||||
glm::mat4 projection;
|
||||
glm::mat4 lightview;
|
||||
glm::vec3 scene_extra;
|
||||
float time;
|
||||
};
|
||||
|
||||
static_assert(sizeof(scene_ubs) == 144, "bad size of ubs");
|
||||
|
||||
const size_t MAX_PARAMS = 3;
|
||||
|
||||
struct model_ubs
|
||||
{
|
||||
glm::mat4 modelview;
|
||||
glm::mat3x4 modelviewnormal;
|
||||
glm::vec4 param[MAX_PARAMS];
|
||||
|
||||
glm::mat4 future;
|
||||
float opacity;
|
||||
float emission;
|
||||
float fog_density;
|
||||
float alpha_mult;
|
||||
UBS_PAD(4);
|
||||
|
||||
void set_modelview(const glm::mat4 &mv)
|
||||
{
|
||||
modelview = mv;
|
||||
modelviewnormal = glm::mat3x4(glm::mat3(glm::transpose(glm::inverse(mv))));
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(model_ubs) == 196 + 16 * MAX_PARAMS, "bad size of ubs");
|
||||
|
||||
struct light_element_ubs
|
||||
{
|
||||
enum type_e
|
||||
{
|
||||
SPOT = 0,
|
||||
POINT,
|
||||
DIR
|
||||
};
|
||||
|
||||
glm::vec3 pos;
|
||||
type_e type;
|
||||
|
||||
glm::vec3 dir;
|
||||
float in_cutoff;
|
||||
|
||||
glm::vec3 color;
|
||||
float out_cutoff;
|
||||
|
||||
float linear;
|
||||
float quadratic;
|
||||
|
||||
float intensity;
|
||||
float ambient;
|
||||
};
|
||||
|
||||
static_assert(sizeof(light_element_ubs) == 64, "bad size of ubs");
|
||||
|
||||
const size_t MAX_LIGHTS = 8;
|
||||
|
||||
struct light_ubs
|
||||
{
|
||||
glm::vec3 ambient;
|
||||
UBS_PAD(4);
|
||||
|
||||
glm::vec3 fog_color;
|
||||
uint32_t lights_count;
|
||||
|
||||
light_element_ubs lights[MAX_LIGHTS];
|
||||
};
|
||||
|
||||
static_assert(sizeof(light_ubs) == 32 + sizeof(light_element_ubs) * MAX_LIGHTS, "bad size of ubs");
|
||||
|
||||
#pragma pack(pop)
|
||||
}
|
||||
85
gl/vao.cpp
Normal file
85
gl/vao.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include "stdafx.h"
|
||||
#include "vao.h"
|
||||
|
||||
bool gl::vao::use_vao = true;
|
||||
|
||||
gl::vao::vao()
|
||||
{
|
||||
if (!use_vao)
|
||||
return;
|
||||
|
||||
glGenVertexArrays(1, *this);
|
||||
}
|
||||
|
||||
gl::vao::~vao()
|
||||
{
|
||||
if (!use_vao)
|
||||
return;
|
||||
|
||||
unbind();
|
||||
glDeleteVertexArrays(1, *this);
|
||||
}
|
||||
|
||||
void gl::vao::setup_attrib(gl::buffer &buffer, int attrib, int size, int type, int stride, int offset)
|
||||
{
|
||||
if (use_vao) {
|
||||
bind();
|
||||
buffer.bind(buffer::ARRAY_BUFFER);
|
||||
glVertexAttribPointer(attrib, size, type, GL_FALSE, stride, reinterpret_cast<void*>(offset));
|
||||
glEnableVertexAttribArray(attrib);
|
||||
}
|
||||
else {
|
||||
params.push_back({buffer, attrib, size, type, stride, offset});
|
||||
active = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void gl::vao::setup_ebo(buffer &e)
|
||||
{
|
||||
if (use_vao) {
|
||||
bind();
|
||||
e.bind(buffer::ELEMENT_ARRAY_BUFFER);
|
||||
}
|
||||
else {
|
||||
ebo = &e;
|
||||
active = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void gl::vao::bind()
|
||||
{
|
||||
if (active == this)
|
||||
return;
|
||||
active = this;
|
||||
|
||||
if (use_vao) {
|
||||
glBindVertexArray(*this);
|
||||
}
|
||||
else {
|
||||
for (attrib_params ¶m : params) {
|
||||
param.buffer.bind(gl::buffer::ARRAY_BUFFER);
|
||||
glVertexAttribPointer(param.attrib, param.size, param.type, GL_FALSE, param.stride, reinterpret_cast<void*>(param.offset));
|
||||
glEnableVertexAttribArray(param.attrib);
|
||||
}
|
||||
|
||||
for (size_t i = params.size(); i < 4; i++)
|
||||
glDisableVertexAttribArray(i);
|
||||
|
||||
if (ebo)
|
||||
ebo->bind(gl::buffer::ELEMENT_ARRAY_BUFFER);
|
||||
else
|
||||
gl::buffer::unbind(gl::buffer::ELEMENT_ARRAY_BUFFER);
|
||||
}
|
||||
}
|
||||
|
||||
void gl::vao::unbind()
|
||||
{
|
||||
active = nullptr;
|
||||
if (use_vao) {
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
else {
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
glDisableVertexAttribArray(i);
|
||||
}
|
||||
}
|
||||
37
gl/vao.h
Normal file
37
gl/vao.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "object.h"
|
||||
#include "bindable.h"
|
||||
#include "buffer.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
class vao : object, public bindable<vao>
|
||||
{
|
||||
struct attrib_params {
|
||||
// TBD: should be shared_ptr? (when buffer is destroyed by owner VAO could still potentially exist)
|
||||
gl::buffer &buffer;
|
||||
|
||||
int attrib;
|
||||
int size;
|
||||
int type;
|
||||
int stride;
|
||||
int offset;
|
||||
};
|
||||
buffer *ebo = nullptr;
|
||||
|
||||
std::vector<attrib_params> params;
|
||||
|
||||
public:
|
||||
vao();
|
||||
~vao();
|
||||
|
||||
void setup_attrib(buffer &buffer, int attrib, int size, int type, int stride, int offset);
|
||||
void setup_ebo(buffer &ebo);
|
||||
|
||||
void bind();
|
||||
static void unbind();
|
||||
|
||||
static bool use_vao;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user