the usual triangle test with the shader pipeline
This commit is contained in:
parent
1f6ff8526b
commit
351d29cd54
10 changed files with 263 additions and 105 deletions
|
@ -32,4 +32,4 @@ target_include_directories(
|
||||||
include
|
include
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(pwscripting lualib pwcore pwsystem pwscene)
|
target_link_libraries(pwscripting lualib pwcore pwsystem pwscene pwvisual)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "script_core.hpp"
|
#include "script_core.hpp"
|
||||||
#include "script_system.hpp"
|
#include "script_system.hpp"
|
||||||
#include "script_scene.hpp"
|
#include "script_scene.hpp"
|
||||||
|
#include "script_visual.hpp"
|
||||||
|
|
||||||
namespace pw {
|
namespace pw {
|
||||||
|
|
||||||
|
@ -46,6 +47,7 @@ void lua_state::load_modules() {
|
||||||
script_core::load(_namespace);
|
script_core::load(_namespace);
|
||||||
script_system::load(_namespace);
|
script_system::load(_namespace);
|
||||||
script_scene::load(_namespace);
|
script_scene::load(_namespace);
|
||||||
|
script_visual::load(_namespace);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,27 +6,8 @@
|
||||||
|
|
||||||
#include "pw/core/debug.hpp"
|
#include "pw/core/debug.hpp"
|
||||||
|
|
||||||
// hijacking
|
|
||||||
//#include "pw/visual/pipeline.hpp"
|
|
||||||
|
|
||||||
namespace pw {
|
namespace pw {
|
||||||
|
|
||||||
#if defined(__clang)
|
|
||||||
struct window_lua : public window {
|
|
||||||
// overridable function
|
|
||||||
sol::function lua_update;
|
|
||||||
|
|
||||||
window_lua(sol::this_state L)
|
|
||||||
// default is an empty callback
|
|
||||||
: lua_update(sol::make_reference<sol::function>(L.lua_state(), [](){}))
|
|
||||||
{
|
|
||||||
// set this internal callback of the window to the lua callback
|
|
||||||
_on_update = [this](window&){this->lua_update();};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void script_system::load(sol::table &ns)
|
void script_system::load(sol::table &ns)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -41,30 +22,20 @@ void script_system::load(sol::table &ns)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
ns.new_usertype<input>("input",
|
ns.new_usertype<input>("input",
|
||||||
"new", sol::no_constructor,
|
"new", sol::no_constructor,
|
||||||
"get",&input::get,
|
"get",&input::get,
|
||||||
"mouse_position",sol::readonly_property(&input::mouse_position),
|
"mouse_position",sol::readonly_property(&input::mouse_position),
|
||||||
"mouse_button",sol::readonly_property(&input::mouse_button),
|
"mouse_button",sol::readonly_property(&input::mouse_button),
|
||||||
"mouse_pressed",sol::readonly_property(&input::mouse_pressed),
|
"mouse_pressed",sol::readonly_property(&input::mouse_pressed),
|
||||||
"input_string",sol::readonly_property(&input::input_string)
|
"input_string",sol::readonly_property(&input::input_string)
|
||||||
);
|
);
|
||||||
|
|
||||||
ns.new_usertype<display>("display",
|
ns.new_usertype<display>("display",
|
||||||
"all",&display::all,
|
"all",&display::all,
|
||||||
"name",sol::readonly_property(&display::name)
|
"name",sol::readonly_property(&display::name)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// ns.set_function("my_class_func_2", &my_class::func);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// // hijack part
|
|
||||||
// //
|
|
||||||
// ns.new_usertype<pipeline>("pipeline",
|
|
||||||
// "create",&pipeline::create
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include "script_visual.hpp"
|
||||||
|
|
||||||
|
#include "pw/core/debug.hpp"
|
||||||
|
#include "pw/visual/pipeline.hpp"
|
||||||
|
|
||||||
|
namespace pw {
|
||||||
|
|
||||||
|
void script_visual::load(sol::table &ns)
|
||||||
|
{
|
||||||
|
|
||||||
|
ns.new_usertype<pipeline>("pipeline",
|
||||||
|
"create",&pipeline::create,
|
||||||
|
"draw",&pipeline::draw
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef PW_SCRIPTING_PRIVATE_VISUAL_HPP
|
||||||
|
#define PW_SCRIPTING_PRIVATE_VISUAL_HPP
|
||||||
|
|
||||||
|
#include "scripting.hpp"
|
||||||
|
|
||||||
|
namespace pw {
|
||||||
|
|
||||||
|
struct script_visual {
|
||||||
|
|
||||||
|
static void load(scripting::table& ns);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -70,9 +70,18 @@ local w = pw.window.new()
|
||||||
-- set title
|
-- set title
|
||||||
w.title = "pixwerx 0.1"
|
w.title = "pixwerx 0.1"
|
||||||
|
|
||||||
|
local pl = pw.pipeline.new()
|
||||||
|
if pl:create(pw.size.new(800,600)) then
|
||||||
|
print("pipeline ok")
|
||||||
|
else
|
||||||
|
print("pipeline failed")
|
||||||
|
end
|
||||||
|
|
||||||
-- setup a lua callback function
|
-- setup a lua callback function
|
||||||
w.on_update = function(self)
|
w.on_update = function(self)
|
||||||
print("test on update",w.position.x,w.position.y,pw.timer.now)
|
|
||||||
|
pl:draw()
|
||||||
|
-- print("test on update",w.position.x,w.position.y,pw.timer.now)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set size
|
-- set size
|
||||||
|
@ -90,16 +99,16 @@ local t = pw.timer.new()
|
||||||
while w:update()
|
while w:update()
|
||||||
do
|
do
|
||||||
-- somehow works
|
-- somehow works
|
||||||
if (pw.input.get().input_string == 'f') then
|
if (pw.input.get().input_string == 'f') then
|
||||||
w.fullscreen = not w.fullscreen
|
w.fullscreen = not w.fullscreen
|
||||||
end
|
end
|
||||||
|
|
||||||
-- just to check
|
-- just to check
|
||||||
if (pw.input:get().mouse_button == 1) then
|
if (pw.input:get().mouse_button == 1) then
|
||||||
print("elapsed",t.elapsed)
|
print("elapsed",t.elapsed)
|
||||||
t:reset()
|
t:reset()
|
||||||
print(pw.input:get().mouse_position.x,pw.input:get().mouse_position.y)
|
print(pw.input:get().mouse_position.x,pw.input:get().mouse_position.y)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- print("update")
|
-- print("update")
|
||||||
end
|
end
|
||||||
|
|
|
@ -135,9 +135,9 @@ struct window::impl {
|
||||||
|
|
||||||
update_display_list();
|
update_display_list();
|
||||||
|
|
||||||
// request specific version 3.2
|
// request specific version 3.3
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ class shader {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
shader();
|
shader();
|
||||||
|
~shader();
|
||||||
|
|
||||||
enum code_type {
|
enum code_type {
|
||||||
vertex, //<
|
vertex, //<
|
||||||
|
@ -21,7 +22,7 @@ public:
|
||||||
compute
|
compute
|
||||||
};
|
};
|
||||||
|
|
||||||
void set_source(const std::string& c,code_type t);
|
void set_source(const std::string& c,code_type t) { _source[t] = c; }
|
||||||
std::string source(code_type t) { return _source[t]; }
|
std::string source(code_type t) { return _source[t]; }
|
||||||
|
|
||||||
// void set_attributes(const std::vector<std::string> > &attributes);
|
// void set_attributes(const std::vector<std::string> > &attributes);
|
||||||
|
@ -41,6 +42,10 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void build();
|
||||||
|
|
||||||
|
void use();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
std::map<code_type,std::string> _source;
|
std::map<code_type,std::string> _source;
|
||||||
|
|
|
@ -2,91 +2,208 @@
|
||||||
#include "pw/core/size.hpp"
|
#include "pw/core/size.hpp"
|
||||||
#include "pw/core/matrix.hpp"
|
#include "pw/core/matrix.hpp"
|
||||||
|
|
||||||
|
#include "pw/core/debug.hpp"
|
||||||
#include "pw/visual/pipeline.hpp"
|
#include "pw/visual/pipeline.hpp"
|
||||||
|
#include "pw/visual/shader.hpp"
|
||||||
|
|
||||||
#include "glad/glad.h"
|
#include "glad/glad.h"
|
||||||
|
|
||||||
namespace pw {
|
namespace pw {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct triangle_renderer
|
||||||
|
{
|
||||||
|
GLuint vbo = 0;
|
||||||
|
GLuint vao = 0;
|
||||||
|
GLuint shader_programme = 0;
|
||||||
|
|
||||||
|
shader shader_p;
|
||||||
|
|
||||||
|
triangle_renderer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
float points[] = {
|
||||||
|
0.0f, 0.5f, 0.0f,
|
||||||
|
0.5f, -0.5f, 0.0f,
|
||||||
|
-0.5f, -0.5f, 0.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
glGenBuffers(1, &vbo);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), points, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &vao);
|
||||||
|
glBindVertexArray(vao);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
|
||||||
|
|
||||||
|
const char* vertex_shader =
|
||||||
|
"#version 400\n"
|
||||||
|
"in vec3 vp;"
|
||||||
|
"void main() {"
|
||||||
|
" gl_Position = vec4(vp, 1.0);"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
|
||||||
|
const char* fragment_shader =
|
||||||
|
"#version 400\n"
|
||||||
|
"out vec4 frag_colour;"
|
||||||
|
"void main() {"
|
||||||
|
" frag_colour = vec4(0.5, 0.0, 0.5, 1.0);"
|
||||||
|
"}";
|
||||||
|
#if 0
|
||||||
|
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
glShaderSource(vs, 1, &vertex_shader, NULL);
|
||||||
|
glCompileShader(vs);
|
||||||
|
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
glShaderSource(fs, 1, &fragment_shader, NULL);
|
||||||
|
glCompileShader(fs);
|
||||||
|
|
||||||
|
shader_programme = glCreateProgram();
|
||||||
|
glAttachShader(shader_programme, fs);
|
||||||
|
glAttachShader(shader_programme, vs);
|
||||||
|
glLinkProgram(shader_programme);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
shader_p.set_source(fragment_shader,shader::fragment);
|
||||||
|
shader_p.set_source(vertex_shader,shader::vertex);
|
||||||
|
|
||||||
|
shader_p.build();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw()
|
||||||
|
{
|
||||||
|
// glUseProgram(shader_programme);
|
||||||
|
|
||||||
|
|
||||||
|
shader_p.use();
|
||||||
|
glBindVertexArray(vao);
|
||||||
|
// draw points 0-3 from the currently bound VAO with current in-use shader
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct pipeline::impl {
|
struct pipeline::impl {
|
||||||
|
|
||||||
sizei _size;
|
sizei _size;
|
||||||
|
|
||||||
GLuint _fbo_draw;
|
GLuint _fbo_draw;
|
||||||
GLuint _fbo_msaa;
|
GLuint _fbo_msaa;
|
||||||
|
|
||||||
GLuint rboColorId;
|
GLuint rboColorId;
|
||||||
GLuint rboDepthId;
|
GLuint rboDepthId;
|
||||||
|
|
||||||
bool create(sizei size);
|
//testing
|
||||||
|
triangle_renderer tr;
|
||||||
|
|
||||||
void draw();
|
bool create(sizei size);
|
||||||
|
|
||||||
impl() = default;
|
void draw();
|
||||||
~impl() = default;
|
|
||||||
|
impl() = default;
|
||||||
|
~impl() = default;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool pipeline::impl::create(sizei size)
|
bool pipeline::impl::create(sizei size)
|
||||||
{
|
{
|
||||||
int max_msaa;
|
|
||||||
|
|
||||||
// query actual maximum MSAA
|
_size = size;
|
||||||
glGetIntegerv(GL_MAX_SAMPLES,&max_msaa);
|
|
||||||
|
|
||||||
// create a 4x MSAA renderbuffer object for colorbuffer
|
int max_msaa;
|
||||||
int msaa = 4;
|
|
||||||
|
|
||||||
// msaa = std::clamp(msaa,max_msaa);
|
// query actual maximum MSAA
|
||||||
|
glGetIntegerv(GL_MAX_SAMPLES,&max_msaa);
|
||||||
|
|
||||||
glGenRenderbuffers(1, &rboColorId);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, rboColorId);
|
|
||||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_RGB8, _size.width, _size.height);
|
|
||||||
|
|
||||||
// create a 4x MSAA renderbuffer object for depthbuffer
|
// create a 4x MSAA renderbuffer object for colorbuffer
|
||||||
|
int msaa = std::min(max_msaa,4);
|
||||||
|
|
||||||
glGenRenderbuffers(1, &rboDepthId);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, rboDepthId);
|
|
||||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_DEPTH_COMPONENT, _size.width, _size.height);
|
|
||||||
|
|
||||||
// create a 4x MSAA framebuffer object
|
debug::d() << "OpenGL multisampling: " << max_msaa << " choosen:" << msaa;
|
||||||
glGenFramebuffers(1, &_fbo_msaa);
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, _fbo_msaa);
|
|
||||||
|
|
||||||
// attach colorbuffer image to FBO
|
// msaa = std::clamp(msaa,max_msaa);
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, // 1. fbo target: GL_FRAMEBUFFER
|
|
||||||
GL_COLOR_ATTACHMENT0, // 2. color attachment point
|
|
||||||
GL_RENDERBUFFER, // 3. rbo target: GL_RENDERBUFFER
|
|
||||||
rboColorId); // 4. rbo ID
|
|
||||||
|
|
||||||
// attach depthbuffer image to FBO
|
glGenRenderbuffers(1, &rboColorId);
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, // 1. fbo target: GL_FRAMEBUFFER
|
glBindRenderbuffer(GL_RENDERBUFFER, rboColorId);
|
||||||
GL_DEPTH_ATTACHMENT, // 2. depth attachment point
|
glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_RGB8, _size.width, _size.height);
|
||||||
GL_RENDERBUFFER, // 3. rbo target: GL_RENDERBUFFER
|
|
||||||
rboDepthId); // 4. rbo ID
|
|
||||||
|
|
||||||
// check FBO status
|
// create a 4x MSAA renderbuffer object for depthbuffer
|
||||||
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
glGenRenderbuffers(1, &rboDepthId);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, rboDepthId);
|
||||||
|
glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_DEPTH_COMPONENT, _size.width, _size.height);
|
||||||
|
|
||||||
|
// create a 4x MSAA framebuffer object
|
||||||
|
glGenFramebuffers(1, &_fbo_msaa);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, _fbo_msaa);
|
||||||
|
|
||||||
|
// attach colorbuffer image to FBO
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, // 1. fbo target: GL_FRAMEBUFFER
|
||||||
|
GL_COLOR_ATTACHMENT0, // 2. color attachment point
|
||||||
|
GL_RENDERBUFFER, // 3. rbo target: GL_RENDERBUFFER
|
||||||
|
rboColorId); // 4. rbo ID
|
||||||
|
|
||||||
|
// attach depthbuffer image to FBO
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, // 1. fbo target: GL_FRAMEBUFFER
|
||||||
|
GL_DEPTH_ATTACHMENT, // 2. depth attachment point
|
||||||
|
GL_RENDERBUFFER, // 3. rbo target: GL_RENDERBUFFER
|
||||||
|
rboDepthId); // 4. rbo ID
|
||||||
|
|
||||||
|
// check FBO status
|
||||||
|
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
tr.setup();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pipeline::impl::draw()
|
void pipeline::impl::draw()
|
||||||
{
|
{
|
||||||
/* We are going to blit into the window (default framebuffer) */
|
|
||||||
glBindFramebuffer (GL_DRAW_FRAMEBUFFER, 0);
|
|
||||||
glDrawBuffer (GL_BACK); /* Use backbuffer as color dst. */
|
|
||||||
|
|
||||||
/* Read from your FBO */
|
glBindBuffer(GL_DRAW_FRAMEBUFFER, _fbo_draw);
|
||||||
glBindFramebuffer (GL_READ_FRAMEBUFFER, _fbo_draw );
|
|
||||||
glReadBuffer (GL_COLOR_ATTACHMENT0); /* Use Color Attachment 0 as color src. */
|
|
||||||
|
|
||||||
/* Copy the color and depth buffer from your FBO to the default framebuffer */
|
glClearColor(1,0,0,1);
|
||||||
glBlitFramebuffer (0,0, _size.width, _size.height,
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
0,0, _size.width, _size.height,
|
|
||||||
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
|
tr.draw();
|
||||||
GL_NEAREST);
|
|
||||||
|
// reset
|
||||||
|
glBindBuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
|
||||||
|
// actuall blitting
|
||||||
|
|
||||||
|
/* We are going to blit into the window (default framebuffer) */
|
||||||
|
glBindFramebuffer (GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
glDrawBuffer (GL_BACK); /* Use backbuffer as color dst. */
|
||||||
|
|
||||||
|
/* Read from your FBO */
|
||||||
|
glBindFramebuffer (GL_READ_FRAMEBUFFER, _fbo_draw );
|
||||||
|
glReadBuffer (GL_COLOR_ATTACHMENT0); /* Use Color Attachment 0 as color src. */
|
||||||
|
|
||||||
|
/* Copy the color and depth buffer from your FBO to the default framebuffer */
|
||||||
|
glBlitFramebuffer (0,0, _size.width, _size.height,
|
||||||
|
0,0, _size.width, _size.height,
|
||||||
|
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
|
||||||
|
GL_LINEAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,7 +212,7 @@ void pipeline::impl::draw()
|
||||||
//
|
//
|
||||||
|
|
||||||
pipeline::pipeline()
|
pipeline::pipeline()
|
||||||
: _impl(std::make_unique<pipeline::impl>())
|
: _impl(std::make_unique<pipeline::impl>())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +221,14 @@ pipeline::~pipeline()
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pipeline::draw()
|
||||||
|
{
|
||||||
|
_impl->draw();
|
||||||
|
}
|
||||||
|
|
||||||
bool pipeline::create(size s)
|
bool pipeline::create(size s)
|
||||||
{
|
{
|
||||||
return _impl->create(sizei(s.width,s.height));
|
return _impl->create(s.cast<int>());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,7 +159,11 @@ struct shader::impl
|
||||||
|
|
||||||
shader::shader()
|
shader::shader()
|
||||||
{
|
{
|
||||||
_impl = make_unique<impl>(*this);
|
_impl = make_unique<impl>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
shader::~shader()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shader::ready() const
|
bool shader::ready() const
|
||||||
|
@ -167,6 +171,16 @@ bool shader::ready() const
|
||||||
return _impl->is_valid();
|
return _impl->is_valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void shader::build()
|
||||||
|
{
|
||||||
|
_impl->build();
|
||||||
|
}
|
||||||
|
|
||||||
|
void shader::use()
|
||||||
|
{
|
||||||
|
_impl->use();
|
||||||
|
}
|
||||||
|
|
||||||
int shader::uniform_location(const std::string &name)
|
int shader::uniform_location(const std::string &name)
|
||||||
{
|
{
|
||||||
return _impl->uniform_location(name);
|
return _impl->uniform_location(name);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue