From: Eleni Maria Stea Date: Thu, 15 Mar 2018 01:52:43 +0000 (+0200) Subject: Changed the OpenGL part and the GLSL shaders to use UBO and X-Git-Url: http://git.mutantstargoat.com?a=commitdiff_plain;ds=sidebyside;h=05d269a194496bcef85da78652b947f5bf1c9bcf;hp=6cecb8f16f1863496884ca86790375dbb27138ba;p=demo Changed the OpenGL part and the GLSL shaders to use UBO and locations inside the shaders. Introduced new abstraction on top of UBO functions so that both OpenGL and Vulkan can use them from the renderer --- diff --git a/gl_shaders/default.f.glsl b/gl_shaders/default.f.glsl index ad4b77a..fe78fbc 100644 --- a/gl_shaders/default.f.glsl +++ b/gl_shaders/default.f.glsl @@ -1,45 +1,38 @@ #version 450 -uniform sampler2D tex; -uniform samplerCube dstex; +#define SHADING_UNIFORMS 1 -uniform vec4 diffuse; -uniform vec4 specular; -uniform float shininess; +layout(binding = 0) uniform sampler2D tex; +layout(binding = 1) uniform samplerCube dstex; -varying vec3 pos; -// varying vec3 normal; -// varying vec3 ldir; -varying vec2 tex_coord; -varying vec3 world_normal; +layout(std140, binding = SHADING_UNIFORMS) uniform fu { + vec4 diffuse; + vec4 specular; + float shininess; + float fog_density; +} s; -// const float fog_density = 0.005; -uniform float fog_density; const vec3 sky_color = vec3(0.35, 0.5, 0.65); +// const float fog_density = 0.005; + +/* varyings */ +layout(location = 4) in vec3 pos; +layout(location = 5) in vec2 tex_coord; +layout(location = 6) in vec3 world_normal; -out vec4 color; +layout(location = 0) out vec4 color; void main() { vec4 itexel = textureCube(dstex, normalize(world_normal)); -/* vec3 p = normalize(pos); // view space dir - vec3 n = normalize(normal); - vec3 l = normalize(ldir); - - vec3 r = normalize(-reflect(l, n)); - vec3 vdir = normalize(-p); - - float cdiff = max(dot(l, n), 0.0); - float cspec = pow(max(dot(r, vdir), 0.0), shininess); */ - float dist = -pos.z; - float fog = clamp(exp(-fog_density * dist), 0.0, 1.0); + float fog = clamp(exp(-s.fog_density * dist), 0.0, 1.0); vec4 texel = texture2D(tex, tex_coord); // vec3 object_color = (diffuse.xyz * cdiff * texel.xyz + specular.xyz * cspec) * itexel.xyz; - vec3 object_color = diffuse.xyz * texel.xyz * itexel.xyz; + vec3 object_color = s.diffuse.xyz * texel.xyz * itexel.xyz; color.xyz = mix(sky_color, object_color, fog); color.w = 1.0; diff --git a/gl_shaders/default.v.glsl b/gl_shaders/default.v.glsl index 76aae8a..b550308 100644 --- a/gl_shaders/default.v.glsl +++ b/gl_shaders/default.v.glsl @@ -1,15 +1,12 @@ #version 450 -//#extension GL_ARB_separate_shader_objects : enable -uniform mat4 mview; -uniform mat4 mmviewproj; -uniform mat4 mmod; +#define MATRIX_UNIFORMS 0 -varying vec3 pos; -// varying vec3 normal; -// varying vec3 ldir; -varying vec2 tex_coord; -varying vec3 world_normal; +layout(std140, binding = MATRIX_UNIFORMS) uniform vu { + mat4 mview; + uniform mat4 mmviewproj; + uniform mat4 mmod; +} m; const vec3 lpos = vec3(-10.0, 100.0, 10.0); @@ -18,16 +15,17 @@ layout(location = 1) in vec3 attr_pos; layout(location = 2) in vec3 attr_normal; layout(location = 3) in vec2 attr_tex; +/* varyings */ +layout(location = 4) out vec3 pos; +layout(location = 5) out vec2 tex_coord; +layout(location = 6) out vec3 world_normal; + void main() { - gl_Position = mmviewproj * vec4(attr_pos, 1.0); - - pos = (mview * vec4(attr_pos, 1.0)).xyz; - // ldir = (mview * vec4(lpos, 1.0)).xyz; + gl_Position = m.mmviewproj * vec4(attr_pos, 1.0); - // mat3 normal_matrix = mat3(mview); - // normal = normal_matrix * attr_normal; + pos = (m.mview * vec4(attr_pos, 1.0)).xyz; tex_coord = attr_tex; - world_normal = (mmod * vec4(attr_normal, 1.0)).xyz; -} \ No newline at end of file + world_normal = (m.mmod * vec4(attr_normal, 1.0)).xyz; +} diff --git a/gl_shaders/morphing.f.glsl b/gl_shaders/morphing.f.glsl index ddb0579..de6dda9 100644 --- a/gl_shaders/morphing.f.glsl +++ b/gl_shaders/morphing.f.glsl @@ -1,41 +1,33 @@ #version 450 -uniform sampler2D tex; -uniform samplerCube dstex; +#define SHADING_UNIFORMS 1 -uniform vec4 diffuse; -// uniform vec4 specular; -// uniform float shininess; +layout(binding = 0) uniform sampler2D tex; +layout(binding = 1) uniform samplerCube dstex; -uniform float fog_density; -const vec3 sky_color = vec3(0.35, 0.5, 0.65); +layout(std140, binding = SHADING_UNIFORMS) uniform fu { + vec4 diffuse; + vec4 specular; + float shininess; + float fog_density; +} s; + +/* varyings */ +layout(location = 4) in vec3 pos; +layout(location = 5) in vec2 tex_coord; +layout(location = 6) in vec3 world_normal; -varying vec3 pos; -// varying vec3 normal; -// varying vec3 ldir; -varying vec2 tex_coord; -varying vec3 world_normal; +layout(location = 0) out vec4 color; -out vec4 color; +const vec3 sky_color = vec3(0.35, 0.5, 0.65); void main() { vec4 itexel = textureCube(dstex, normalize(world_normal)); - // vec3 p = normalize(pos); - // vec3 n = normalize(normal); - // vec3 l = normalize(ldir); - - // vec3 r = normalize(-reflect(l, n)); - // vec3 vdir = normalize(-p); - - // float cdiff = max(dot(l, n), 0.0); - // float cspec = pow(max(dot(r, vdir), 0.0), shininess); - vec4 texel = texture2D(tex, tex_coord); - // vec3 object_color = diffuse.xyz * cdiff * texel.xyz + specular.xyz * cspec; - vec3 object_color = diffuse.xyz * texel.xyz * itexel.xyz; + vec3 object_color = s.diffuse.xyz * texel.xyz * itexel.xyz; float dist = -pos.z; - float fog = clamp(exp(-fog_density * dist), 0.0, 1.0); + float fog = clamp(exp(-s.fog_density * dist), 0.0, 1.0); color.xyz = mix(sky_color, object_color, fog); color.w = 1.0; diff --git a/gl_shaders/morphing.v.glsl b/gl_shaders/morphing.v.glsl index d84336f..80b7e39 100644 --- a/gl_shaders/morphing.v.glsl +++ b/gl_shaders/morphing.v.glsl @@ -1,25 +1,30 @@ #version 450 -uniform mat4 mview; -uniform mat4 mmviewproj; -uniform mat4 mmod; +#define MATRIX_UNIFORMS 0 +#define MORPHING_UNIFORMS 3 -uniform float t; -const float half_height = 0.855; - -varying vec3 pos; -// varying vec3 normal; -// varying vec3 ldir; -varying vec2 tex_coord; -varying vec3 world_normal; +layout(std140, binding = MATRIX_UNIFORMS) uniform vu { + mat4 mview; + uniform mat4 mmviewproj; + uniform mat4 mmod; +} m; -// const vec3 lpos = vec3(0.0, 100.0, -10.0); +layout(std140, binding = MORPHING_UNIFORMS) uniform mvu { + float t; +} time; /* attributes */ layout(location = 1) in vec3 attr_pos; layout(location = 2) in vec3 attr_normal; layout(location = 3) in vec2 attr_tex; +/* varyings */ +layout(location = 4) out vec3 pos; +layout(location = 5) out vec2 tex_coord; +layout(location = 6) out vec3 world_normal; + +const float half_height = 0.855; + void main() { vec3 sph_pos = normalize(vec3(attr_pos.x, attr_pos.y - half_height, attr_pos.z)); @@ -27,17 +32,13 @@ void main() vec3 sph_normal = sph_pos; sph_pos.y += half_height; - vec3 p = mix(attr_pos, sph_pos, t); - vec3 n = mix(attr_normal, sph_normal, t); - - gl_Position = mmviewproj * vec4(p, 1.0); + vec3 p = mix(attr_pos, sph_pos, time.t); + vec3 n = mix(attr_normal, sph_normal, time.t); - pos = (mview * vec4(p, 1.0)).xyz; - // ldir = (mview * vec4(lpos, 1.0)).xyz; + gl_Position = m.mmviewproj * vec4(p, 1.0); - // mat3 normal_matrix = mat3(mview); - // normal = normal_matrix * n; + pos = (m.mview * vec4(p, 1.0)).xyz; tex_coord = attr_tex; - world_normal = (mmod * vec4(attr_normal, 1.0)).xyz; -} \ No newline at end of file + world_normal = (m.mmod * vec4(attr_normal, 1.0)).xyz; +} diff --git a/gl_shaders/sky.f.glsl b/gl_shaders/sky.f.glsl index d5009c0..688da43 100644 --- a/gl_shaders/sky.f.glsl +++ b/gl_shaders/sky.f.glsl @@ -1,6 +1,6 @@ #version 450 -uniform samplerCube stex; +layout(binding = 0) uniform samplerCube stex; in vec3 normal; out vec4 color; @@ -11,4 +11,4 @@ void main() color.rgb = texel.rgb; color.a = 1.0; -} \ No newline at end of file +} diff --git a/gl_shaders/sky.v.glsl b/gl_shaders/sky.v.glsl index 84097a0..f5ba24f 100644 --- a/gl_shaders/sky.v.glsl +++ b/gl_shaders/sky.v.glsl @@ -1,6 +1,11 @@ #version 450 -uniform mat4 mviewproj; +#define SKY_MATRIX_UNIFORMS 2 + +layout(std140, binding = SKY_MATRIX_UNIFORMS) uniform svu { + mat4 mviewproj; +} s; + layout(location = 1) in vec3 attr_pos; layout(location = 2) in vec3 attr_normal; @@ -9,6 +14,6 @@ out vec3 normal; void main() { - gl_Position = mviewproj * vec4(attr_pos, 1.0); + gl_Position = s.mviewproj * vec4(attr_pos, 1.0); normal = attr_normal; -} \ No newline at end of file +} diff --git a/src/camera.cc b/src/camera.cc index b3ad077..7de5501 100644 --- a/src/camera.cc +++ b/src/camera.cc @@ -3,16 +3,10 @@ #include #include "camera.h" -#include "state_manager.h" Camera::Camera() {} Camera::~Camera() {} -void Camera::use() const -{ - state_manager.set_state("st_view_matrix", get_view_matrix()); -} - OrbitCamera::OrbitCamera() { phi = theta = distance = 0; @@ -63,4 +57,4 @@ void OrbitCamera::set_position(float x, float y, float z) position.x = x; position.y = y; position.z = z; -} \ No newline at end of file +} diff --git a/src/camera.h b/src/camera.h index 1fbbf9c..0f70040 100644 --- a/src/camera.h +++ b/src/camera.h @@ -9,7 +9,6 @@ public: virtual ~Camera(); virtual Mat4 get_view_matrix() const = 0; - virtual void use() const; }; class OrbitCamera : public Camera { @@ -32,4 +31,4 @@ public: Mat4 calc_projection_matrix(float fov_deg, float aspect, float n, float f); -#endif // CAMERA_H_ \ No newline at end of file +#endif // CAMERA_H_ diff --git a/src/gfxapi.cc b/src/gfxapi.cc index 1b67a36..e9f0f73 100644 --- a/src/gfxapi.cc +++ b/src/gfxapi.cc @@ -6,10 +6,12 @@ #include "opengl/mesh-gl.h" #include "opengl/texture-gl.h" #include "opengl/shader-gl.h" +#include "opengl/uniforms-gl.h" #include "vulkan/shader-vk.h" #include "vulkan/mesh-vk.h" #include "vulkan/texture-vk.h" +#include "vulkan/uniforms-vk.h" static Gfx_API api; @@ -97,6 +99,17 @@ Shader *gfx_create_shader() return 0; } +UniformBuffer *gfx_create_uniform_buffer() +{ + switch(api) { + case GFX_GL: + return new UniformBufferGL; + case GFX_VK: + return new UniformBufferVK; + } + return 0; +} + char *gfx_get_shader_path() { switch(api) { diff --git a/src/gfxapi.h b/src/gfxapi.h index 80d996a..d6b1fd1 100644 --- a/src/gfxapi.h +++ b/src/gfxapi.h @@ -2,9 +2,10 @@ #define GFXAPI_H_ class Mesh; -class Texture; class ShaderProgram; class Shader; +class Texture; +class UniformBuffer; enum Gfx_API { GFX_GL, @@ -34,6 +35,8 @@ Mesh *gfx_create_mesh(); Texture *gfx_create_texture(); ShaderProgram *gfx_create_shader_program(); Shader *gfx_create_shader(); +UniformBuffer *gfx_create_uniform_buffer(); + char *gfx_get_shader_path(); #endif // GFXAPI_H_ diff --git a/src/morph_renderer.cc b/src/morph_renderer.cc index d076114..a691835 100644 --- a/src/morph_renderer.cc +++ b/src/morph_renderer.cc @@ -1,10 +1,15 @@ #include "global.h" +#include "gfxapi.h" + #include "morph_renderer.h" #include "object.h" #include "scene.h" #include "shader.h" #include "shader_manager.h" #include "texture.h" +#include "uniforms.h" + +#define MVU 5 MorphRenderer::MorphRenderer() { @@ -17,10 +22,13 @@ MorphRenderer::MorphRenderer() dskytex = 0; fog_density = 0; + + mbuf = vbuf = fbuf = svbuf = 0; } MorphRenderer::~MorphRenderer() { + delete mbuf; } bool MorphRenderer::create() @@ -29,28 +37,40 @@ bool MorphRenderer::create() return false; } - /* getting material uniform locations: diffuse, specular, specular exponent (strength) */ - - diff_loc = sprog->get_uniform_location("diffuse"); - spec_loc = sprog->get_uniform_location("specular"); - shin_loc = sprog->get_uniform_location("shininess"); - t_loc = sprog->get_uniform_location("t"); - fog_loc = sprog->get_uniform_location("fog_density"); + mbuf = gfx_create_uniform_buffer(); + if(!mbuf->create(sizeof mu)) { + fprintf(stderr, "Failed to create uniform buffer.\n"); + return false; + } - /* uniform locations for matrices */ + if(!vbuf) { + vbuf = gfx_create_uniform_buffer(); + if(!vbuf->create(sizeof vu)) { + fprintf(stderr, "Failed to create uniform buffer.\n"); + return false; + } + } - mmviewproj_loc = sprog->get_uniform_location("mmviewproj"); - mview_loc = sprog->get_uniform_location("mview"); - mmod_loc = sprog->get_uniform_location("mmod"); + if(!fbuf) { + fbuf = gfx_create_uniform_buffer(); + if(!fbuf->create(sizeof fu)) { + fprintf(stderr, "Failed to create uniform buffer.\n"); + return false; + } + } - dstex_loc = sprog->get_uniform_location("dstex"); - if(dstex_loc != -1) - sprog->set_uniformi(dstex_loc, 1); + if(!svbuf) { + svbuf = gfx_create_uniform_buffer(); + if(!svbuf->create(sizeof svu)) { + fprintf(stderr, "Failed to create uniform buffer.\n"); + return false; + } + } return true; } -void MorphRenderer::draw() const +void MorphRenderer::draw() { if(!camera || !scene) return; @@ -65,13 +85,14 @@ void MorphRenderer::draw() const sprog->use(); for(size_t i=0; iobjects.size(); i++) { - float t = (sin(time_sec + 7.3 * noise(i * M_PI)) + 1) * 0.5; - if(t_loc != -1) - sprog->set_uniformf(t_loc, t); + mu.t = (sin(time_sec + 7.3 * noise(i * M_PI)) + 1) * 0.5; + mbuf->update(&mu); + mbuf->bind(MORPHING_UNIFORMS); - if(mmod_loc != -1) - sprog->set_uniform_matrix(mmod_loc, scene->objects[i]->transform.upper3x3()); + vu.mmod = scene->objects[i]->transform.upper3x3(); + vbuf->update(&vu); + vbuf->bind(MATRIX_UNIFORMS); draw_object(scene->objects[i]); } -} \ No newline at end of file +} diff --git a/src/morph_renderer.h b/src/morph_renderer.h index c939b4b..d4812a9 100644 --- a/src/morph_renderer.h +++ b/src/morph_renderer.h @@ -3,16 +3,28 @@ #include "renderer.h" +class UniformBuffer; + +struct MorphVertUniforms { + float t; +}; + +struct MorphFragUniforms { + float fog_density; + Vec4 diffuse; +}; + class MorphRenderer : public Renderer { protected: - int t_loc; + MorphVertUniforms mu; + UniformBuffer *mbuf; public: MorphRenderer(); virtual ~MorphRenderer(); virtual bool create() override; - virtual void draw() const override; + virtual void draw() override; }; -#endif // MORPH_RENDERER_H_ \ No newline at end of file +#endif // MORPH_RENDERER_H_ diff --git a/src/opengl/shader-gl.cc b/src/opengl/shader-gl.cc index 374673f..296a67c 100644 --- a/src/opengl/shader-gl.cc +++ b/src/opengl/shader-gl.cc @@ -2,7 +2,6 @@ #include #include -#include "state_manager.h" #include "opengl/shader-gl.h" ShaderGL::ShaderGL() @@ -156,92 +155,3 @@ void ShaderProgramGL::attach_shader(Shader *shader) glAttachShader(prog, ((ShaderGL *)shader)->sdr); is_linked = false; } - -int ShaderProgramGL::get_uniform_location(const char *name) const -{ - if(!use()) - return -1; - - return glGetUniformLocation(prog, name); -} - -void ShaderProgramGL::set_uniformi(int location, int value) -{ - if(!use() || location == -1) { - return; - } - - glUniform1i(location, value); -} - -void ShaderProgramGL::set_uniformi(int location, int x, int y) -{ - if(!use() || location == -1) { - return; - } - - glUniform2i(location, x, y); -} - -void ShaderProgramGL::set_uniformi(int location, int x, int y, int z) -{ - if(!use() || location == -1) { - return; - } - - glUniform3i(location, x, y, z); -} - -void ShaderProgramGL::set_uniformi(int location, int x, int y, int z, int w) -{ - if(!use() || location == -1) { - return; - } - - glUniform4i(location, x, y, z, w); -} - -void ShaderProgramGL::set_uniformf(int location, float value) -{ - if(!use() || location == -1) { - return; - } - - glUniform1f(location, value); -} - -void ShaderProgramGL::set_uniformf(int location, float x, float y) -{ - if(!use() || location == -1) { - return; - } - - glUniform2f(location, x, y); -} - -void ShaderProgramGL::set_uniformf(int location, float x, float y, float z) -{ - if(!use() || location == -1) { - return; - } - - glUniform3f(location, x, y, z); -} - -void ShaderProgramGL::set_uniformf(int location, float x, float y, float z, float w) -{ - if(!use() || location == -1) { - return; - } - - glUniform4f(location, x, y, z, w); -} - -void ShaderProgramGL::set_uniform_matrix(int location, const Mat4 &mat) -{ - if(!use() || location == -1) { - return; - } - - glUniformMatrix4fv(location, 1, GL_FALSE, mat[0]); -} diff --git a/src/opengl/shader-gl.h b/src/opengl/shader-gl.h index d8136f4..4ee4a57 100644 --- a/src/opengl/shader-gl.h +++ b/src/opengl/shader-gl.h @@ -31,20 +31,6 @@ public: virtual bool create() override; virtual void destroy() override; virtual void attach_shader(Shader *shader) override; - - virtual int get_uniform_location(const char *name) const override; - - virtual void set_uniformi(int location, int value) override; - virtual void set_uniformi(int location, int x, int y) override; - virtual void set_uniformi(int location, int x, int y, int z) override; - virtual void set_uniformi(int location, int x, int y, int z, int w) override; - - virtual void set_uniformf(int location, float value) override; - virtual void set_uniformf(int location, float x, float y) override; - virtual void set_uniformf(int location, float x, float y, float z) override; - virtual void set_uniformf(int location, float x, float y, float z, float w) override; - - virtual void set_uniform_matrix(int location, const Mat4 &mat) override; }; -#endif // SHADER_GL_H_ \ No newline at end of file +#endif // SHADER_GL_H_ diff --git a/src/opengl/uniforms-gl.cc b/src/opengl/uniforms-gl.cc new file mode 100644 index 0000000..c4d82d2 --- /dev/null +++ b/src/opengl/uniforms-gl.cc @@ -0,0 +1,39 @@ +#include + +#include "uniforms-gl.h" + +UniformBufferGL::UniformBufferGL() +{ + ubo = 0; +} + +UniformBufferGL::~UniformBufferGL() +{ + destroy(); +} + +bool UniformBufferGL::create(int size) +{ + glGenBuffers(1, &ubo); + glBindBuffer(GL_UNIFORM_BUFFER, ubo); + glBufferData(GL_UNIFORM_BUFFER, size, 0, GL_STREAM_DRAW); + + return UniformBuffer::create(size); +} + +void UniformBufferGL::destroy() +{ + glDeleteBuffers(1, &ubo); +} + +void UniformBufferGL::bind(int binding) const +{ + //glBindBuffer(GL_UNIFORM_BUFFER, ubo); + glBindBufferBase(GL_UNIFORM_BUFFER, binding, ubo); +} + +void UniformBufferGL::update(void *data) +{ + glBindBuffer(GL_UNIFORM_BUFFER, ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, size, data); +} diff --git a/src/opengl/uniforms-gl.h b/src/opengl/uniforms-gl.h new file mode 100644 index 0000000..cfa724e --- /dev/null +++ b/src/opengl/uniforms-gl.h @@ -0,0 +1,21 @@ +#ifndef UNIFORMS_GL_H_ +#define UNIFORMS_GL_H_ + +#include "uniforms.h" + +class UniformBufferGL : public UniformBuffer { +private: + unsigned int ubo; + +public: + UniformBufferGL(); + virtual ~UniformBufferGL(); + + virtual bool create(int size); + virtual void destroy() override; + + virtual void bind(int binding) const override; + virtual void update(void *data) override; +}; + +#endif // UNIFORMS_GL_H_ diff --git a/src/renderer.cc b/src/renderer.cc index fd18d55..11cfb93 100644 --- a/src/renderer.cc +++ b/src/renderer.cc @@ -1,5 +1,4 @@ #include -#include #include "global.h" #include "gfxapi.h" @@ -13,6 +12,7 @@ #include "shader.h" #include "shader_manager.h" #include "texture.h" +#include "uniforms.h" #undef DRAW_NORMALS @@ -20,7 +20,6 @@ static Mesh *skymesh; /* it will be used by many renderers => no destroy */ static ShaderProgram *skyprog; -static int viewproj_loc; Renderer::Renderer() { @@ -32,51 +31,50 @@ Renderer::Renderer() dskytex = 0; fog_density = 0; + + vbuf = fbuf = svbuf = 0; } Renderer::~Renderer() { + delete vbuf; + delete fbuf; + delete svbuf; } bool Renderer::create() { //debug // if(!(nprog = sdr_man->create_shader_program("debug.v.glsl", "debug.f.glsl"))) { - // fprintf(stderr, "Failed to load debug shaders.\n"); + // fprintf(stderr, "Failed to load debug shaders.\n"); // } if(!(sprog = sdr_man->create_shader_program("default.v.glsl", "default.f.glsl"))) { return false; } - /* getting material uniform locations: diffuse, specular, specular exponent (strength) */ - - diff_loc = sprog->get_uniform_location("diffuse"); - spec_loc = sprog->get_uniform_location("specular"); - shin_loc = sprog->get_uniform_location("shininess"); - fog_loc = sprog->get_uniform_location("fog_density"); - - /* uniform locations for matrices */ - - mmviewproj_loc = sprog->get_uniform_location("mmviewproj"); - mview_loc = sprog->get_uniform_location("mview"); - mmod_loc = sprog->get_uniform_location("mmod"); - - /* skybox, irradiance map uniforms */ - - stex_loc = sprog->get_uniform_location("stex"); - dstex_loc = sprog->get_uniform_location("dstex"); + vbuf = gfx_create_uniform_buffer(); + if(!vbuf->create(sizeof vu)) { + fprintf(stderr, "Failed to create uniform buffer.\n"); + return false; + } - if(stex_loc != -1) - sprog->set_uniformi(stex_loc, 0); + fbuf = gfx_create_uniform_buffer(); + if(!fbuf->create(sizeof fu)) { + fprintf(stderr, "Failed to create uniform buffer.\n"); + return false; + } - if(dstex_loc != -1) - sprog->set_uniformi(dstex_loc, 1); + svbuf = gfx_create_uniform_buffer(); + if(!svbuf->create(sizeof svu)) { + fprintf(stderr, "Failed to create uniform buffer.\n"); + return false; + } return true; } -void Renderer::draw() const +void Renderer::draw() { if(!camera || !scene) return; @@ -99,23 +97,19 @@ void Renderer::draw() const } } -void Renderer::draw_object(Object *object) const +void Renderer::draw_object(Object *object) { Material *m = object->material; /* setting uniforms for material */ - if(diff_loc != -1) - sprog->set_uniformf(diff_loc, m->diffuse.x, m->diffuse.y, m->diffuse.z, 1); - - if(spec_loc != -1) - sprog->set_uniformf(spec_loc, m->specular.x, m->specular.y, m->specular.z, 1); + fu.diffuse = Vec4(m->diffuse.x, m->diffuse.y, m->diffuse.z, 1.0); + fu.specular = Vec4(m->specular.x, m->specular.y, m->specular.z, 1.0); + fu.shininess = m->shininess; + fu.fog_density = fog_density; - if(shin_loc != -1) - sprog->set_uniformf(shin_loc, m->shininess); - - if(fog_loc != -1) - sprog->set_uniformf(fog_loc, fog_density); + fbuf->update(&fu); + fbuf->bind(SHADING_UNIFORMS); /* texture */ @@ -124,27 +118,22 @@ void Renderer::draw_object(Object *object) const /* setting uniforms for matrices */ - Mat4 mmviewproj = object->transform * camera->get_view_matrix() * mprojection; - if(mmviewproj_loc != -1) - sprog->set_uniform_matrix(mmviewproj_loc, mmviewproj); - - Mat4 mview = object->transform * camera->get_view_matrix(); - if(mview_loc != -1) - sprog->set_uniform_matrix(mview_loc, mview); + vu.mview = object->transform * camera->get_view_matrix(); + vu.mmviewproj = object->transform * camera->get_view_matrix() * mprojection; + vu.mmod = object->transform.upper3x3(); - Mat4 mmod = object->transform.upper3x3(); - if(mmod_loc != -1) - sprog->set_uniform_matrix(mmod_loc, mmod); + vbuf->update(&vu); + vbuf->bind(MATRIX_UNIFORMS); object->mesh->draw(); // debug #ifdef DRAW_NORMALS if(nprog) { - int loc = nprog->get_uniform_location("mmviewproj"); - if(loc != -1) { - nprog->set_uniform_matrix(loc, mmviewproj); - } + vu.mmviewproj = mmviewproj; + vbuf->update(&vu); + vbuf->bind(MATRIX_UNIFORMS); + nprog->use(); object->mesh->draw_normals(1.0); } @@ -160,8 +149,6 @@ void Renderer::set_sky_tex(Texture *stex) if(!skyprog) { if(!(skyprog = sdr_man->create_shader_program("sky.v.glsl", "sky.f.glsl"))) return; - if((viewproj_loc = skyprog->get_uniform_location("mviewproj") == -1)) - return; } skytex = stex; } @@ -171,7 +158,7 @@ void Renderer::set_diffuse_sky_tex(Texture *dstex) dskytex = dstex; } -void Renderer::draw_skybox() const +void Renderer::draw_skybox() { if(!skymesh || !skytex) return; @@ -182,12 +169,12 @@ void Renderer::draw_skybox() const skytex->bind(); skyprog->use(); - Mat4 mviewproj; - mviewproj = camera->get_view_matrix().upper3x3() * mprojection; - skyprog->set_uniform_matrix(viewproj_loc, mviewproj); + svu.mviewproj = camera->get_view_matrix().upper3x3() * mprojection; + svbuf->update(&svu); + svbuf->bind(SKY_MATRIX_UNIFORMS); skymesh->draw(); gfx_cull_face(GFX_CULL_BACK); gfx_zbuffer(true); -} \ No newline at end of file +} diff --git a/src/renderer.h b/src/renderer.h index 23471f5..9605aa3 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -1,23 +1,50 @@ #ifndef RENDERER_H_ #define RENDERER_H_ +#include + class OrbitCamera; class Object; class Scene; class ShaderProgram; class Texture; +class UniformBuffer; + +enum { + MATRIX_UNIFORMS = 0, + SHADING_UNIFORMS = 1, + SKY_MATRIX_UNIFORMS = 2, + MORPHING_UNIFORMS = 3, + MORPHING_SHADING_UNIFORMS = 4, +}; + +struct BaseVertUniforms { + Mat4 mview; + Mat4 mmviewproj; + Mat4 mmod; +}; + +struct BaseFragUniforms { + Vec4 diffuse; + Vec4 specular; + float shininess; + float fog_density; +}; + +struct SkyVertUniforms { + Mat4 mviewproj; +}; class Renderer { protected: - int diff_loc; - int spec_loc; - int shin_loc; - int mmviewproj_loc; - int mview_loc; - int mmod_loc; - int fog_loc; - int dstex_loc; - int stex_loc; + BaseVertUniforms vu; + UniformBuffer *vbuf; + + BaseFragUniforms fu; + UniformBuffer *fbuf; + + SkyVertUniforms svu; + UniformBuffer *svbuf; ShaderProgram *sprog; @@ -26,8 +53,8 @@ protected: Texture *skytex, *dskytex; - virtual void draw_object(Object *object) const; - virtual void draw_skybox() const; + virtual void draw_object(Object *object); + virtual void draw_skybox(); public: float fog_density; @@ -39,10 +66,10 @@ public: virtual ~Renderer(); virtual bool create(); - virtual void draw() const; + virtual void draw(); virtual void set_sky_tex(Texture *stex); virtual void set_diffuse_sky_tex(Texture *dstex); }; -#endif // RENDERER_H_ \ No newline at end of file +#endif // RENDERER_H_ diff --git a/src/shader.cc b/src/shader.cc index 39fa0de..b39401f 100644 --- a/src/shader.cc +++ b/src/shader.cc @@ -25,7 +25,6 @@ bool Shader::load(const char *fname, SType type) if(!(fp = fopen(fname, "rb"))) { fprintf(stderr, "Failed to open shader: %s\n", fname); - return false; } fseek(fp, 0, SEEK_END); @@ -44,8 +43,7 @@ bool Shader::load(const char *fname, SType type) buf[fsz] = '\0'; fclose(fp); - create(buf, fsz, fname); - return true; + return create(buf, fsz, fname); } SType Shader::get_type() diff --git a/src/shader.h b/src/shader.h index 6e9509a..5a79b7f 100644 --- a/src/shader.h +++ b/src/shader.h @@ -37,16 +37,9 @@ public: /* Shader Program */ -struct Uniform { - int location; - std::string name; - int state_idx; -}; - class ShaderProgram { protected: Shader *shaders[2]; - std::vector uniforms; public: ShaderProgram(); @@ -57,25 +50,6 @@ public: virtual bool use() const = 0; virtual void destroy() = 0; virtual void attach_shader(Shader *shader) = 0; - - /* - THIS PART MIGHT NEED SEVERAL CHANGES: on vulkan we set the uniforms - using descriptor sets. The current design is suitable for OpenGL and - it *might* have to be rewritten to work with both APIs later - */ - virtual int get_uniform_location(const char *name) const = 0; - - virtual void set_uniformi(int location, int value) = 0; - virtual void set_uniformi(int location, int x, int y) = 0; - virtual void set_uniformi(int location, int x, int y, int z) = 0; - virtual void set_uniformi(int location, int x, int y, int z, int w) = 0; - - virtual void set_uniformf(int location, float value) = 0; - virtual void set_uniformf(int location, float x, float y) = 0; - virtual void set_uniformf(int location, float x, float y, float z) = 0; - virtual void set_uniformf(int location, float x, float y, float z, float w) = 0; - - virtual void set_uniform_matrix(int location, const Mat4 &mat) = 0; }; #endif // SHADER_H_ diff --git a/src/state_manager.cc b/src/state_manager.cc deleted file mode 100644 index a375cff..0000000 --- a/src/state_manager.cc +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include -#include - -#include - -#include "state_manager.h" - -StateManager state_manager; - -State *StateManager::get_state(const char *name) -{ - std::map::iterator it; - it = statemap.find(name); - return it == statemap.end() ? 0 : &states[it->second]; -} - -int StateManager::add_state_element(const char *name, int num_floats) -{ - State *st = get_state(name); - if(st) { - if(st->num != num_floats) { - fprintf(stderr, "Uniform %s, type mismatch!\n", name); - return -1; - } - - return st - &states[0]; - } - - State state; - state.num = num_floats; - - state.name = new char[strlen(name) + 1]; - strcpy(state.name, name); - - int sz = sizeof *state.data * num_floats; - state.data = new float[sz]; - memset(state.data, 0, sz); - - int idx = (int)states.size(); - states.push_back(state); - - statemap[name] = idx; - - printf("State manager: added state %s with %d float data.\n", name, num_floats); - return idx; -} - -void StateManager::set_state(const char *name, float value) -{ - set_state(name, Vec4(value, 0, 0, 1)); -} - -void StateManager::set_state(const char *name, const Vec3 &vec) -{ - set_state(name, Vec4(vec.x, vec.y, vec.z, 1)); -} - -void StateManager::set_state(const char *name, const Vec4 &vec) -{ - State *state = get_state(name); - if(!state) - return; - - switch(state->num) { - case 4: - state->data[3] = vec.w; - case 3: - state->data[2] = vec.z; - case 2: - state->data[1] = vec.y; - case 1: - state->data[0] = vec.x; - default: - break; - } -} - -void StateManager::set_state(const char *name, const Mat4 &mat) -{ - State *state = get_state(name); - - if(!state) - return; - - if(state->num != 16) { - fprintf(stderr, "State manager: state %s can only be a 4x4 matrix.\n", name); - return; - } - - for(int j=0; j<4; j++) { - for(int i=0; i<4; i++) { - state->data[4 * i + j] = mat.m[i][j]; - } - } -} - -const State *StateManager::get_state(const char *name) const -{ - return ((StateManager *)this)->get_state(name); -} - -const State *StateManager::get_state(int idx) const -{ - return &states[idx]; -} \ No newline at end of file diff --git a/src/state_manager.h b/src/state_manager.h deleted file mode 100644 index 4894644..0000000 --- a/src/state_manager.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef STATE_MANAGER_H_ -#define STATE_MANAGER_H_ - -#include -#include - -#include -#include - -struct State { - int num; - char *name; - float *data; -}; - -class StateManager { -private: - std::map statemap; - State *get_state(const char *name); - -public: - std::vector states; - - /* - adds a state returns an idx: - the num_floats indicates the number of floats that form - the state element. - For example: - a float value consists of 1 float => num_floats = 1, - a Vec2 consists of 2 floats, a Vec3 from 3, a Vec4 from 4 - - see also: - set_state(const char *name, const Mat4 &mat implementation) - */ - int add_state_element(const char *name, int num_floats); - - void set_state(const char *name, float value); - void set_state(const char *name, const Vec3 &vec); - void set_state(const char *name, const Vec4 &vec); - void set_state(const char *name, const Mat4 &mat); - - const State *get_state(const char *name) const; - const State *get_state(int idx) const; -}; - -extern StateManager state_manager; - -#endif // STATE_MANAGER_H_ \ No newline at end of file diff --git a/src/uniforms.cc b/src/uniforms.cc new file mode 100644 index 0000000..765a5b0 --- /dev/null +++ b/src/uniforms.cc @@ -0,0 +1,16 @@ +#include "uniforms.h" + +UniformBuffer::UniformBuffer() +{ + size = -1; +} + +UniformBuffer::~UniformBuffer() +{ +} + +bool UniformBuffer::create(int size) +{ + this->size = size; + return true; +} diff --git a/src/uniforms.h b/src/uniforms.h new file mode 100644 index 0000000..9117135 --- /dev/null +++ b/src/uniforms.h @@ -0,0 +1,19 @@ +#ifndef UNIFORMS_H_ +#define UNIFORMS_H_ + +class UniformBuffer { +protected: + int size; + +public: + UniformBuffer(); + virtual ~UniformBuffer(); + + virtual bool create(int size); + virtual void destroy() = 0; + + virtual void bind(int binding) const = 0; + virtual void update(void *data) = 0; +}; + +#endif // UNIFORMS_H_ diff --git a/src/vulkan/allocator.cc b/src/vulkan/allocator.cc index ba1b47b..60da2c8 100644 --- a/src/vulkan/allocator.cc +++ b/src/vulkan/allocator.cc @@ -34,7 +34,7 @@ void vku_free(VkDeviceMemory gpu_memory) bool vku_write_memory(VkDeviceMemory gpu_mem, int size, void *data) { uint8_t *pdata; - VkResult res = vkMapMemory(vk_device, gpu_mem, 0, size, 0, (void**)&pdata); + VkResult res = vkMapMemory(vk_device, gpu_mem, 0, size, 0, (void **)&pdata); if(res != VK_SUCCESS) { fprintf(stderr, "Failed to map memory to write data.\n"); return false; diff --git a/src/vulkan/mesh-vk.cc b/src/vulkan/mesh-vk.cc index 729e24c..540501e 100644 --- a/src/vulkan/mesh-vk.cc +++ b/src/vulkan/mesh-vk.cc @@ -52,14 +52,14 @@ bool MeshVK::update_vertex_data() int vsz = vertices.size() * sizeof(Vec3); if(!(vk_vertices = vku_create_buffer(vsz, - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))) { + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))) { fprintf(stderr, "Failed to create the buffer for the vertices.\n"); return false; } int nsz = normals.size() * sizeof(Vec3); if(!(vk_normals = vku_create_buffer(nsz, - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))) { + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))) { vku_destroy_buffer(vk_vertices); fprintf(stderr, "Failed to create the buffer for the normals.\n"); @@ -68,18 +68,18 @@ bool MeshVK::update_vertex_data() int tsz = tex_coords.size() * sizeof(Vec2); if(!(vk_tex_coords = vku_create_buffer(tsz, - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))) { + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))) { vku_destroy_buffer(vk_vertices); vku_destroy_buffer(vk_normals); fprintf(stderr, - "Failed to create the buffer for the texture coordinates.\n"); + "Failed to create the buffer for the texture coordinates.\n"); return false; } int isz = indices.size() * 2; if(!(vk_indices = vku_create_buffer(isz, - VK_BUFFER_USAGE_INDEX_BUFFER_BIT))) { + VK_BUFFER_USAGE_INDEX_BUFFER_BIT))) { vku_destroy_buffer(vk_vertices); vku_destroy_buffer(vk_normals); vku_destroy_buffer(vk_tex_coords); @@ -90,43 +90,43 @@ bool MeshVK::update_vertex_data() /* write the buffers */ - if(!vku_write_memory(vk_vertices->mem_pool, vsz, (void*)vertices.data())) { + if(!vku_write_memory(vk_vertices->mem_pool, vsz, (void *)vertices.data())) { fprintf(stderr, "Failed to write the vertices to GPU.\n"); return false; } if(vkBindBufferMemory(vk_device, vk_vertices->buf, vk_vertices->mem_pool, - 0) != VK_SUCCESS) { + 0) != VK_SUCCESS) { fprintf(stderr, "Failed to bind the vertex buffer memory\n"); return false; } - if(!vku_write_memory(vk_normals->mem_pool, nsz, (void*)normals.data())) { + if(!vku_write_memory(vk_normals->mem_pool, nsz, (void *)normals.data())) { fprintf(stderr, "Failed to write the normals to GPU.\n"); return false; } if(vkBindBufferMemory(vk_device, vk_normals->buf, vk_normals->mem_pool, 0) - != VK_SUCCESS) { + != VK_SUCCESS) { fprintf(stderr, "Failed to bind the normal buffer memory\n"); return false; } if(!vku_write_memory(vk_tex_coords->mem_pool, tsz, - (void*)tex_coords.data())) { + (void *)tex_coords.data())) { fprintf(stderr, "Failed to write the texture coordinates to GPU.\n"); return false; } if(vkBindBufferMemory(vk_device, vk_tex_coords->buf, - vk_tex_coords->mem_pool, 0) != VK_SUCCESS) { + vk_tex_coords->mem_pool, 0) != VK_SUCCESS) { fprintf(stderr, "Failed to bind the tex coordinates buffer memory.\n"); return false; } - if(!vku_write_memory(vk_indices->mem_pool, isz, (void*)indices.data())) { + if(!vku_write_memory(vk_indices->mem_pool, isz, (void *)indices.data())) { fprintf(stderr, "Failed to write the indices to GPU.\n"); return false; } if(vkBindBufferMemory(vk_device, vk_indices->buf, vk_indices->mem_pool, 0) - != VK_SUCCESS) { + != VK_SUCCESS) { fprintf(stderr, "Failed to bind the index buffer memory.\n"); return false; } diff --git a/src/vulkan/shader-vk.cc b/src/vulkan/shader-vk.cc index d53883d..1fa9fb3 100644 --- a/src/vulkan/shader-vk.cc +++ b/src/vulkan/shader-vk.cc @@ -39,7 +39,7 @@ bool ShaderVK::create(char *buf, unsigned int bsz, const char *fname) sminf.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; sminf.codeSize = bsz; - sminf.pCode = (uint32_t*)buf; + sminf.pCode = (uint32_t *)buf; if(vkCreateShaderModule(vk_device, &sminf, 0, &sm) != VK_SUCCESS) { delete [] buf; @@ -100,7 +100,7 @@ bool ShaderProgramVK::create() fprintf(stderr, "Failed to create graphics pipeline: Invalid shader type.\n"); return false; } - ssinf[i].module = ((ShaderVK*)shaders[i])->sm; + ssinf[i].module = ((ShaderVK *)shaders[i])->sm; } gpinf.pStages = ssinf; @@ -125,45 +125,3 @@ void ShaderProgramVK::destroy() void ShaderProgramVK::attach_shader(Shader *shader) { } - -int ShaderProgramVK::get_uniform_location(const char *name) const -{ - return 0; -} - -void ShaderProgramVK::set_uniformi(int location, int value) -{ -} - -void ShaderProgramVK::set_uniformi(int location, int x, int y) -{ -} - -void ShaderProgramVK::set_uniformi(int location, int x, int y, int z) -{ -} - -void ShaderProgramVK::set_uniformi(int location, int x, int y, int z, int w) -{ -} - - -void ShaderProgramVK::set_uniformf(int location, float value) -{ -} - -void ShaderProgramVK::set_uniformf(int location, float x, float y) -{ -} - -void ShaderProgramVK::set_uniformf(int location, float x, float y, float z) -{ -} - -void ShaderProgramVK::set_uniformf(int location, float x, float y, float z, float w) -{ -} - -void ShaderProgramVK::set_uniform_matrix(int location, const Mat4 &mat) -{ -} diff --git a/src/vulkan/shader-vk.h b/src/vulkan/shader-vk.h index b9e4681..efc576f 100644 --- a/src/vulkan/shader-vk.h +++ b/src/vulkan/shader-vk.h @@ -41,19 +41,5 @@ public: virtual bool link() override; virtual void destroy() override; virtual void attach_shader(Shader *shader) override; - - virtual int get_uniform_location(const char *name) const override; - - virtual void set_uniformi(int location, int value) override; - virtual void set_uniformi(int location, int x, int y) override; - virtual void set_uniformi(int location, int x, int y, int z) override; - virtual void set_uniformi(int location, int x, int y, int z, int w) override; - - virtual void set_uniformf(int location, float value) override; - virtual void set_uniformf(int location, float x, float y) override; - virtual void set_uniformf(int location, float x, float y, float z) override; - virtual void set_uniformf(int location, float x, float y, float z, float w) override; - - virtual void set_uniform_matrix(int location, const Mat4 &mat) override; }; #endif // SHADER_VK_H_ diff --git a/src/vulkan/uniforms-vk.cc b/src/vulkan/uniforms-vk.cc new file mode 100644 index 0000000..1c87a55 --- /dev/null +++ b/src/vulkan/uniforms-vk.cc @@ -0,0 +1,26 @@ +#include "uniforms-vk.h" + +UniformBufferVK::UniformBufferVK() +{ +} + +UniformBufferVK::~UniformBufferVK() +{ +} + +bool UniformBufferVK::create(int size) +{ + return true; +} + +void UniformBufferVK::destroy() +{ +} + +void UniformBufferVK::bind(int binding) const +{ +} + +void UniformBufferVK::update(void *data) +{ +} diff --git a/src/vulkan/uniforms-vk.h b/src/vulkan/uniforms-vk.h new file mode 100644 index 0000000..68847ce --- /dev/null +++ b/src/vulkan/uniforms-vk.h @@ -0,0 +1,18 @@ +#ifndef UNIFORMS_VK_H_ +#define UNIFORMS_VK_H_ + +#include "uniforms.h" + +class UniformBufferVK : public UniformBuffer { +public: + UniformBufferVK(); + virtual ~UniformBufferVK(); + + virtual bool create(int size); + virtual void destroy() override; + + virtual void bind(int binding) const override; + virtual void update(void *data) override; +}; + +#endif //UNIFORMS_VK_H_