a working version with no error but still some bugs around texturing
This commit is contained in:
parent
2d8244386a
commit
68d4610470
16 changed files with 473 additions and 110 deletions
|
@ -42,7 +42,7 @@ vector3 vector3_from_lua_table(sol::table t)
|
|||
}
|
||||
|
||||
|
||||
void register_core_function(sol::state&,sol::table& ns)
|
||||
void register_core_function(sol::state& lua,sol::table& ns)
|
||||
{
|
||||
|
||||
typedef real_t Scalar;
|
||||
|
@ -114,7 +114,7 @@ void register_core_function(sol::state&,sol::table& ns)
|
|||
|
||||
|
||||
ns.new_usertype<size>("size"
|
||||
, sol::constructors<size(),size(Scalar,Scalar)>()
|
||||
, sol::call_constructor,sol::constructors<size(),size(Scalar,Scalar)>()
|
||||
, "width",&size::width
|
||||
, "height",&size::height
|
||||
, "cast_to_float",&size::cast<float>
|
||||
|
@ -174,15 +174,24 @@ void register_core_function(sol::state&,sol::table& ns)
|
|||
|
||||
|
||||
|
||||
ns.new_usertype<image>("image"
|
||||
auto image_type = ns.new_usertype<image>("image"
|
||||
, sol::constructors<image()>()
|
||||
,"create",&image::create
|
||||
,"size",sol::readonly_property(&image::size)
|
||||
,"change_count",sol::property(&image::change_count,&image::set_change_count)
|
||||
).new_enum<false>("layout"
|
||||
,"rgb8", image::RGB8
|
||||
,"rgb32", image::RGBA8
|
||||
,"gray", image::LUM);
|
||||
,"create",&image::create
|
||||
,"size",sol::readonly_property(&image::size)
|
||||
,"generate_noise",&image::generate_noise
|
||||
,"change_count",sol::property(&image::change_count,&image::set_change_count)
|
||||
);
|
||||
|
||||
image_type.create_named("pixel_layout"
|
||||
,"rgb8", image::RGB8
|
||||
,"rgb32", image::RGBA8
|
||||
,"gray", image::LUM
|
||||
);
|
||||
|
||||
// image_type["layout"] = lua.create_table_with(
|
||||
// "rgb8", image::RGB8
|
||||
// ,"rgb32", image::RGBA8
|
||||
// ,"gray", image::LUM);
|
||||
|
||||
|
||||
ns.new_usertype<rectangle>("rectangle"
|
||||
|
|
|
@ -30,8 +30,12 @@ void register_visual_function(sol::state&,sol::table &ns)
|
|||
,"set_source",&shader::set_source
|
||||
,"set_uniforms",&shader::set_uniforms
|
||||
,"set_uniform_float",&shader::set_uniform<float>
|
||||
,"set_uniform_uint",&shader::set_uniform<uint32_t>
|
||||
,"set_uniform_int",&shader::set_uniform<int32_t>
|
||||
,"set_uniform_mat4",&shader::set_uniform<matrix4x4&>
|
||||
,"set_uniform_vec4",&shader::set_uniform<vector4&>
|
||||
,"set_uniform_texture",&shader::set_uniform<texture&>
|
||||
|
||||
).new_enum<false>("shader_type"
|
||||
,"fragment",shader::code_type::fragment
|
||||
,"vertex",shader::code_type::vertex
|
||||
|
@ -60,14 +64,19 @@ void register_visual_function(sol::state&,sol::table &ns)
|
|||
,"blit",&framebuffer::blit);
|
||||
|
||||
ns.new_usertype<texture>("texture"
|
||||
,sol::constructors<texture(),texture(texture::image_ref,texture::data_layout)>()
|
||||
,"image",sol::property(&texture::set_image,&texture::image)
|
||||
,sol::constructors<texture()>()
|
||||
,"create",&texture::create
|
||||
,"update",&texture::update
|
||||
,"bind",&texture::bind
|
||||
,"unbind",&texture::unbind
|
||||
,"native_handle",&texture::native_handle
|
||||
);
|
||||
|
||||
ns.new_usertype<context>("context"
|
||||
,sol::constructors<context()>()
|
||||
,"clear",&context::clear
|
||||
,"set_viewport",&context::set_viewport
|
||||
,"get_error",&context::get_error
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,9 +43,9 @@ public:
|
|||
HDR
|
||||
};
|
||||
|
||||
image(const size& s, pixel_layout t, void *ptr = nullptr);
|
||||
image(const size& s, pixel_layout t, const void *ptr = nullptr);
|
||||
|
||||
bool create(const size& s, pixel_layout t, void *ptr = nullptr);
|
||||
bool create(const size& s, pixel_layout t, const void *ptr = nullptr);
|
||||
|
||||
void release(bool release_memory = false);
|
||||
|
||||
|
@ -63,10 +63,9 @@ public:
|
|||
|
||||
static uint32_t bytes_per_pixel(pixel_layout t);
|
||||
|
||||
typedef shared_ptr<image> ptr;
|
||||
|
||||
::pw::size size() const;
|
||||
|
||||
void generate_noise();
|
||||
protected:
|
||||
|
||||
::pw::size _size;
|
||||
|
|
|
@ -1,35 +1,51 @@
|
|||
#include "pw/core/image.hpp"
|
||||
#include "pw/core/debug.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <random>
|
||||
|
||||
namespace pw {
|
||||
|
||||
image::image(const ::pw::size &s, image::pixel_layout t, void *ptr)
|
||||
image::image(const ::pw::size &s, image::pixel_layout t, const void *ptr)
|
||||
{
|
||||
this->create(s,t,ptr);
|
||||
if (!this->create(s,t,ptr)) {
|
||||
debug::w() << __PRETTY_FUNCTION__ << " create failed";
|
||||
}
|
||||
}
|
||||
|
||||
bool image::create(const ::pw::size &s, image::pixel_layout t, void *ptr)
|
||||
bool image::create(const ::pw::size &s,
|
||||
image::pixel_layout t,
|
||||
const void *ptr)
|
||||
{
|
||||
size_t n = bytes_per_pixel(t) * s.area();
|
||||
_size = s;
|
||||
_layout = t;
|
||||
|
||||
if (ptr != nullptr) {
|
||||
|
||||
auto a = reinterpret_cast<image::data_t*>(ptr);
|
||||
|
||||
const auto a = reinterpret_cast<const image::data_t*>(ptr);
|
||||
_data.assign(a,a + n);
|
||||
_size = s;
|
||||
_layout = t;
|
||||
|
||||
} else {
|
||||
|
||||
_data.resize(n);
|
||||
_size = ::pw::size(0,0);
|
||||
}
|
||||
|
||||
return !_data.empty();
|
||||
}
|
||||
|
||||
void image::generate_noise()
|
||||
{
|
||||
std::random_device rd;
|
||||
std::mt19937_64 gen(rd());
|
||||
std::uniform_int_distribution<std::uint8_t> dis;
|
||||
|
||||
std::for_each(_data.begin(),_data.end(),[&](auto& v) {v = static_cast<std::byte>(dis(gen)); });
|
||||
|
||||
|
||||
_change_count++;
|
||||
}
|
||||
|
||||
void image::release(bool release_memory)
|
||||
{
|
||||
_data.clear();
|
||||
|
@ -48,6 +64,8 @@ uint32_t image::bytes_per_pixel(image::pixel_layout t)
|
|||
return 1 * sizeof(data_t);
|
||||
case pw::image::DEPTH:
|
||||
return 1 * sizeof(float);
|
||||
default:
|
||||
debug::w() << __PRETTY_FUNCTION__ << " unhandled pixel_layout";
|
||||
}
|
||||
|
||||
return std::numeric_limits<uint32_t>::max();
|
||||
|
|
|
@ -3,6 +3,7 @@ set(scripts_demo
|
|||
${CMAKE_SOURCE_DIR}/src/scripts/demos/simple_000.lua
|
||||
${CMAKE_SOURCE_DIR}/src/scripts/demos/simple_001.lua
|
||||
${CMAKE_SOURCE_DIR}/src/scripts/demos/simple_002.lua
|
||||
${CMAKE_SOURCE_DIR}/src/scripts/demos/simple_003.lua
|
||||
)
|
||||
|
||||
set(scripts_test
|
||||
|
|
229
src/scripts/demos/simple_003.lua
Normal file
229
src/scripts/demos/simple_003.lua
Normal file
|
@ -0,0 +1,229 @@
|
|||
--
|
||||
-- pixwerx - bare rendering engine binding usage
|
||||
--
|
||||
|
||||
-- we need everything
|
||||
pw.script:load_all()
|
||||
|
||||
print(pw.path.get().executable_path)
|
||||
print(pw.path.get().resource_path)
|
||||
|
||||
local img = pw.image.new()
|
||||
if not img:create(pw.size(64,64),pw.pixel_layout.rgb8) then
|
||||
print("image couldnt be created")
|
||||
end
|
||||
|
||||
-- generate some noise
|
||||
img:generate_noise()
|
||||
|
||||
-- create a window (remember windows are invisible by default)
|
||||
local w = pw.window.new()
|
||||
|
||||
-- set title
|
||||
w.title = "pixwerx - bare rendering"
|
||||
|
||||
-- set size
|
||||
w.size = pw.size(640,480)
|
||||
|
||||
-- move window
|
||||
w.position = pw.point.new(100,100)
|
||||
|
||||
-- create a new geometry
|
||||
local g = pw.geometry:new()
|
||||
|
||||
g.primitive_topology = pw.primitive_topology_type.triangle_list -- meh
|
||||
|
||||
z = -5.0
|
||||
s = 1
|
||||
|
||||
-- geometry can only build with indexed facesets
|
||||
g.vertices:add(pw.vector3:new(-s, s, z)) -- 0
|
||||
g.vertices:add(pw.vector3:new(-s,-s, z)) -- 1
|
||||
g.vertices:add(pw.vector3:new( s,-s, z)) -- 2
|
||||
g.vertices:add(pw.vector3:new( s, s, z)) -- 3
|
||||
|
||||
-- 0 --- 3
|
||||
-- | \ |
|
||||
-- 1 --- 2
|
||||
|
||||
g.indices:add(0)
|
||||
g.indices:add(1)
|
||||
g.indices:add(2)
|
||||
|
||||
g.indices:add(2)
|
||||
g.indices:add(3)
|
||||
g.indices:add(0)
|
||||
|
||||
|
||||
local mm = pw.matrix4x4:new()
|
||||
local mv = pw.matrix4x4:new()
|
||||
local mp = pw.matrix4x4:new()
|
||||
|
||||
local s = pw.shader:new()
|
||||
|
||||
s:set_source(pw.shader_type.vertex,[[
|
||||
#version 400
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
in vec3 vertex_p;
|
||||
|
||||
void main() {
|
||||
gl_Position = projection * view * model * vec4(vertex_p, 1.0);
|
||||
}
|
||||
]])
|
||||
|
||||
s:set_source(pw.shader_type.fragment,[[
|
||||
#version 400
|
||||
uniform vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
uniform sampler2D tex_color;
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
void main() {
|
||||
frag_color = texture(tex_color,vec2(1.0,1.0));
|
||||
}
|
||||
]])
|
||||
|
||||
-- check if the shader can be compiled and linked
|
||||
if not s:build() then
|
||||
print("Error!")
|
||||
end
|
||||
|
||||
|
||||
-- the renderer for a geometry
|
||||
local renderer = pw.renderer:new()
|
||||
|
||||
if not renderer:create(g) then
|
||||
print("couldn't create renderer")
|
||||
end
|
||||
|
||||
-- camera position
|
||||
local cam_pos = pw.vector3:new(0,0,0)
|
||||
|
||||
local model_pos = pw.vector3:new(0,0,0)
|
||||
|
||||
|
||||
local ctx = pw.context:new()
|
||||
|
||||
local tx = pw.texture:new()
|
||||
tx:create(img)
|
||||
|
||||
w.on_resize = function(self)
|
||||
-- use client_size to resize the viewport
|
||||
ctx:set_viewport(pw.rectangle:new(pw.point:new(0,0),self.client_size:cast_to_float()))
|
||||
end
|
||||
|
||||
|
||||
-- setup a lua callback function as callback
|
||||
w.on_update = function(self)
|
||||
|
||||
-- set identity on model matrix
|
||||
mm:set_identity()
|
||||
|
||||
-- set view matrix with look_at - view matrix is moving the world - hence inverse!
|
||||
mv = pw.matrixtransform.look_at(cam_pos,cam_pos + pw.vector3.forward(),pw.vector3.up()):inverse()
|
||||
|
||||
-- compute aspect ratio from canvas size
|
||||
aspect_ratio = self.client_size.width / self.client_size.height
|
||||
|
||||
-- create a view frustum for a perspective projection
|
||||
mp = pw.matrixtransform.perspective_projection(1.3,aspect_ratio,0.2,100)
|
||||
|
||||
-- just some toying around
|
||||
local color_red = pw.mathf.ping_pong(pw.time.now,1.0)
|
||||
local color_green = pw.mathf.ping_pong(pw.time.now + 1,1.0)
|
||||
local color_blue = 1.0 - pw.mathf.ping_pong(pw.time.now,1.0)
|
||||
local cl = pw.vector4:new( color_red, color_green, color_blue, 1.0 )
|
||||
|
||||
img:generate_noise()
|
||||
|
||||
tx:update(img)
|
||||
|
||||
|
||||
-- print(img.change_count)
|
||||
|
||||
-- bind the shader
|
||||
s:use()
|
||||
|
||||
|
||||
|
||||
|
||||
-- update the uniforms, currently the slow path
|
||||
s:set_uniform_mat4("model",mm)
|
||||
|
||||
|
||||
|
||||
s:set_uniform_mat4("view",mv)
|
||||
s:set_uniform_mat4("projection",mp)
|
||||
s:set_uniform_vec4("color",cl)
|
||||
|
||||
s:set_uniform_texture("tex_color",tx)
|
||||
|
||||
|
||||
tx:bind()
|
||||
|
||||
-- draw
|
||||
renderer:draw()
|
||||
|
||||
tx:unbind()
|
||||
|
||||
local e = ctx:get_error()
|
||||
if e ~= 0 then
|
||||
print("OpenGL error",e)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- before entering the update loop make the window visible
|
||||
w.visible = true
|
||||
|
||||
-- main update loop
|
||||
while w:update() do
|
||||
|
||||
-- only check if get a new input
|
||||
if pw.input.get().has_input then
|
||||
|
||||
-- somehow works
|
||||
if pw.input.get().input_string == 'f' then
|
||||
w.fullscreen = not w.fullscreen
|
||||
end
|
||||
|
||||
-- keycode for quit
|
||||
if pw.input.get().input_string == 'q' then
|
||||
break
|
||||
end
|
||||
|
||||
-- just to quickly modify speed
|
||||
local move_step = 0.05
|
||||
|
||||
-- camera
|
||||
if pw.input.get().input_string == 'w' then
|
||||
cam_pos.z = cam_pos.z - move_step
|
||||
elseif pw.input.get().input_string == 's' then
|
||||
cam_pos.z = cam_pos.z + move_step
|
||||
elseif pw.input.get().input_string == 'a' then
|
||||
cam_pos.x = cam_pos.x - move_step
|
||||
elseif pw.input.get().input_string == 'd' then
|
||||
cam_pos.x = cam_pos.x + move_step
|
||||
elseif pw.input.get().input_string == 'z' then
|
||||
cam_pos.y = cam_pos.y + move_step
|
||||
elseif pw.input.get().input_string == 'x' then
|
||||
cam_pos.y = cam_pos.y - move_step
|
||||
end
|
||||
|
||||
-- just some debugging
|
||||
print(cam_pos.x,cam_pos.y,cam_pos.z)
|
||||
|
||||
end
|
||||
|
||||
-- just to check
|
||||
if pw.input:get().mouse_button == 1 then
|
||||
|
||||
print("elapsed",t.elapsed)
|
||||
t:reset()
|
||||
print(pw.input:get().mouse_position.x,pw.input:get().mouse_position.y,w.client_size.width,w.client_size.height)
|
||||
end
|
||||
|
||||
end
|
|
@ -8,8 +8,7 @@ namespace pw {
|
|||
|
||||
class display {
|
||||
public:
|
||||
|
||||
typedef std::vector<display> list;
|
||||
using list = std::vector<display>;
|
||||
|
||||
static const list& all() { return _displays; }
|
||||
|
||||
|
@ -18,9 +17,7 @@ public:
|
|||
protected:
|
||||
|
||||
friend class window;
|
||||
|
||||
std::string _name;
|
||||
|
||||
static list _displays;
|
||||
|
||||
};
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#endif
|
||||
|
||||
// Why? LLVM does not adhere to C++17
|
||||
//#include <filesystem>
|
||||
#include <filesystem>
|
||||
|
||||
namespace pw {
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@ public:
|
|||
|
||||
void clear();
|
||||
|
||||
u_int32_t get_error() const;
|
||||
|
||||
protected:
|
||||
struct impl;
|
||||
std::unique_ptr<impl> _impl;
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace pw {
|
|||
class geometry;
|
||||
|
||||
/**
|
||||
* @brief Connects mesh data with the render backend
|
||||
* @brief builds a renderer for geometry
|
||||
*/
|
||||
class renderer {
|
||||
public:
|
||||
|
|
|
@ -32,6 +32,8 @@ public:
|
|||
bool ready() const;
|
||||
|
||||
shader& set_uniform_at_location(int location,float v);
|
||||
shader& set_uniform_at_location(int location, uint32_t v);
|
||||
shader &set_uniform_at_location(int location, int32_t v);
|
||||
shader& set_uniform_at_location(int location,matrix4x4f const &v);
|
||||
shader& set_uniform_at_location(int location,vector4f const &v);
|
||||
shader& set_uniform_at_location(int location,texture const &t);
|
||||
|
|
|
@ -33,29 +33,28 @@ public:
|
|||
wrap_clamp_to_repeat
|
||||
};
|
||||
|
||||
using image_ref = shared_ptr<::pw::image>;
|
||||
|
||||
texture();
|
||||
texture(image_ref i,data_layout s);
|
||||
texture(const image& i,data_layout s);
|
||||
~texture();
|
||||
|
||||
|
||||
void set_image(image_ref i);
|
||||
image_ref image() const { return _image; }
|
||||
|
||||
void set_shape(data_layout s);
|
||||
void set_shape(data_layout s);
|
||||
data_layout shape() const { return _shape; }
|
||||
|
||||
void set_wrap(wrap_mode w);
|
||||
wrap_mode wrap() const { return _wrap; }
|
||||
|
||||
uint32_t native_handle() const;
|
||||
uint32_t native_sampler_handle() const;
|
||||
|
||||
bool create(const image &i);
|
||||
void update(const image &i);
|
||||
|
||||
void bind();
|
||||
void unbind();
|
||||
|
||||
bool valid() const;
|
||||
|
||||
protected:
|
||||
|
||||
image_ref _image;
|
||||
|
||||
data_layout _shape = data_layout::shape_2d;
|
||||
wrap_mode _wrap = wrap_mode::wrap_clamp_to_edge;
|
||||
|
||||
|
|
|
@ -23,6 +23,12 @@ struct context::impl {
|
|||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
uint32_t get_error() const
|
||||
{
|
||||
return glGetError();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
context::context()
|
||||
|
@ -54,6 +60,11 @@ void context::clear()
|
|||
_impl->clear();
|
||||
}
|
||||
|
||||
u_int32_t context::get_error() const
|
||||
{
|
||||
return _impl->get_error();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -71,12 +71,16 @@ struct renderer::impl {
|
|||
// stop binding
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
#if 0
|
||||
// get errors
|
||||
auto error = glGetError();
|
||||
if (error != GL_NO_ERROR) {
|
||||
debug::e() << __PRETTY_FUNCTION__ << " GL error: " << error;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return ready();
|
||||
}
|
||||
|
||||
|
@ -92,6 +96,7 @@ struct renderer::impl {
|
|||
|
||||
void draw()
|
||||
{
|
||||
|
||||
#if 1
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
|
@ -102,15 +107,18 @@ struct renderer::impl {
|
|||
#endif
|
||||
|
||||
|
||||
|
||||
glBindVertexArray(_vao);
|
||||
glDrawElements(GL_TRIANGLES, _mesh_elements, GL_UNSIGNED_INT, nullptr);
|
||||
glBindVertexArray(0);
|
||||
|
||||
#if 1
|
||||
auto error = glGetError();
|
||||
if (error != GL_NO_ERROR)
|
||||
{
|
||||
debug::e() << "GL error: " << error;
|
||||
debug::e() << __PRETTY_FUNCTION__ << " OpenGL error: " << error;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// GLint get_mode(vertex_array::)
|
||||
|
|
|
@ -49,6 +49,8 @@ struct shader::impl
|
|||
case shader::code_type::fragment:
|
||||
shader_type = GL_FRAGMENT_SHADER;
|
||||
break;
|
||||
default:
|
||||
debug::w() << " unknown shader type";
|
||||
}
|
||||
|
||||
GLuint shaderId = glCreateShader(shader_type);
|
||||
|
@ -156,7 +158,7 @@ struct shader::impl
|
|||
}
|
||||
|
||||
void bind(int location,const matrix3x3f& m)
|
||||
{
|
||||
{
|
||||
glUniformMatrix3fv(location,1,GL_FALSE,m.data);
|
||||
}
|
||||
|
||||
|
@ -175,9 +177,20 @@ struct shader::impl
|
|||
glUniform1f(location,v);
|
||||
}
|
||||
|
||||
void bind(int location,const uint32_t& i)
|
||||
{
|
||||
glUniform1ui(location,i);
|
||||
}
|
||||
|
||||
void bind(int location,const int32_t& i)
|
||||
{
|
||||
glUniform1i(location,i);
|
||||
}
|
||||
|
||||
void bind(int location,const texture& v)
|
||||
{
|
||||
glUniform1d(location,v.native_sampler_handle());
|
||||
this->bind(location,(int)v.native_handle());
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -199,9 +212,21 @@ bool shader::ready() const
|
|||
|
||||
shader &shader::set_uniform_at_location(int location, float v)
|
||||
{
|
||||
_impl->bind(location,v); return *this;
|
||||
_impl->bind(location,v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
shader &shader::set_uniform_at_location(int location, uint32_t v)
|
||||
{
|
||||
_impl->bind(location,v); return *this;
|
||||
}
|
||||
|
||||
shader &shader::set_uniform_at_location(int location, int32_t v)
|
||||
{
|
||||
_impl->bind(location,v); return *this;
|
||||
}
|
||||
|
||||
|
||||
shader &shader::set_uniform_at_location(int location, vector4f const &v)
|
||||
{
|
||||
_impl->bind(location,v); return *this;
|
||||
|
@ -212,6 +237,12 @@ shader &shader::set_uniform_at_location(int location, matrix4x4f const &v)
|
|||
_impl->bind(location,v); return *this;
|
||||
}
|
||||
|
||||
|
||||
shader &shader::set_uniform_at_location(int location, texture const &v)
|
||||
{
|
||||
_impl->bind(location,v); return *this;
|
||||
}
|
||||
|
||||
bool shader::build()
|
||||
{
|
||||
return _impl->build();
|
||||
|
|
|
@ -2,21 +2,24 @@
|
|||
|
||||
#include "glad/glad.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace pw {
|
||||
|
||||
|
||||
struct texture::impl {
|
||||
|
||||
texture &_host;
|
||||
texture &_host;
|
||||
|
||||
GLuint _texture_id;
|
||||
GLuint _texture_sampler;
|
||||
uint32_t _texture_id {0};
|
||||
uint32_t _texture_sampler {0};
|
||||
uint64_t _change_count { std::numeric_limits<uint64_t>::max()};
|
||||
|
||||
impl() = delete;
|
||||
|
||||
impl(texture& host)
|
||||
: _host(host)
|
||||
{
|
||||
impl(texture& host)
|
||||
: _host(host)
|
||||
{
|
||||
}
|
||||
|
||||
~impl()
|
||||
|
@ -24,74 +27,108 @@ struct texture::impl {
|
|||
destroy();
|
||||
}
|
||||
|
||||
GLuint gl_shape() {
|
||||
switch (_host.shape()) {
|
||||
case data_layout::shape_1d:
|
||||
return GL_TEXTURE_1D;
|
||||
case data_layout::shape_2d:
|
||||
return GL_TEXTURE_2D;
|
||||
case data_layout::shape_3d:
|
||||
return GL_TEXTURE_3D;
|
||||
}
|
||||
|
||||
debug::e() << __PRETTY_FUNCTION__ << " unknown texture layout";
|
||||
|
||||
return 0;
|
||||
}
|
||||
bool valid() const {
|
||||
return glIsTexture(_texture_id) > 0;
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
glBindTexture(gl_shape(), _texture_id);
|
||||
glBindTexture(GL_TEXTURE_2D, _texture_id);
|
||||
}
|
||||
|
||||
void unbind()
|
||||
{
|
||||
glBindTexture(gl_shape(), 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void create_sampler()
|
||||
void update(const class image& i)
|
||||
{
|
||||
bind();
|
||||
if (_change_count != i.change_count())
|
||||
{
|
||||
this->bind();
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
|
||||
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
|
||||
i.size().width,i.size().height,
|
||||
GL_RGB,GL_UNSIGNED_BYTE,
|
||||
i.data());
|
||||
|
||||
auto error = glGetError();
|
||||
if (error != GL_NO_ERROR) {
|
||||
debug::e() << __PRETTY_FUNCTION__ << " " << __LINE__ << " GL error: " << error;
|
||||
}
|
||||
|
||||
this->unbind();
|
||||
|
||||
_change_count = i.change_count();
|
||||
}
|
||||
}
|
||||
|
||||
bool create(const class image& i)
|
||||
{
|
||||
if (i.size().area() == 0)
|
||||
{
|
||||
debug::w() << __PRETTY_FUNCTION__ << " empty image";
|
||||
return false;
|
||||
}
|
||||
|
||||
GLuint format = GL_RGB;
|
||||
|
||||
glGenTextures(1, &_texture_id);
|
||||
glActiveTexture(GL_TEXTURE0 + 0);
|
||||
glBindTexture(GL_TEXTURE_2D,_texture_id);
|
||||
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D,0,format,
|
||||
i.size().width,i.size().height,
|
||||
0,format,GL_UNSIGNED_BYTE,
|
||||
i.data()
|
||||
);
|
||||
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
// debug::e() << __PRETTY_FUNCTION__ << " " << __LINE__ << " GL error: " << glGetError();
|
||||
|
||||
|
||||
// create sampler
|
||||
|
||||
#if 0
|
||||
glGenSamplers(1, &_texture_sampler);
|
||||
glBindSampler(0,_texture_sampler);
|
||||
|
||||
glSamplerParameteri(_texture_sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glSamplerParameteri(_texture_sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
// glSamplerParameteri(_texture_sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(_texture_sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(_texture_sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
#endif
|
||||
glBindTexture(GL_TEXTURE_2D,0);
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
void create()
|
||||
{
|
||||
|
||||
auto i = _host._image;
|
||||
|
||||
glGenTextures(1, &_texture_id);
|
||||
glBindTexture(gl_shape(),_texture_id);
|
||||
|
||||
GLuint format = GL_RGBA;
|
||||
|
||||
glTexImage2D(gl_shape(),0,format,i->size().width,i->size().height,0,format,GL_UNSIGNED_BYTE,i->data());
|
||||
|
||||
glGenerateMipmap(gl_shape());
|
||||
// debug::d() << "\t" << " _texture_id " << _texture_id;
|
||||
// debug::d() << "\t" << "_texture_sampler " << _texture_sampler;
|
||||
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
|
||||
// get errors
|
||||
auto error = glGetError();
|
||||
if (error != GL_NO_ERROR) {
|
||||
debug::e() << __PRETTY_FUNCTION__ << " " << __LINE__ << " GL error: " << error;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void destroy()
|
||||
{
|
||||
void destroy()
|
||||
{
|
||||
glDeleteTextures(1,&_texture_id);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@ -106,44 +143,55 @@ texture::texture()
|
|||
{
|
||||
}
|
||||
|
||||
texture::texture(image_ref i, texture::data_layout s)
|
||||
texture::texture(const image &i, texture::data_layout s)
|
||||
{
|
||||
texture();
|
||||
set_image(i);
|
||||
set_shape(s);
|
||||
|
||||
_impl->create();
|
||||
texture();
|
||||
this->create(i);
|
||||
}
|
||||
|
||||
texture::~texture()
|
||||
{
|
||||
}
|
||||
|
||||
void texture::set_image(image_ref i)
|
||||
bool texture::create(const image& i)
|
||||
{
|
||||
_image = i;
|
||||
return _impl->create(i);
|
||||
}
|
||||
|
||||
_impl->create();
|
||||
void texture::update(const image &i)
|
||||
{
|
||||
_impl->update(i);
|
||||
}
|
||||
|
||||
void texture::bind()
|
||||
{
|
||||
_impl->bind();
|
||||
}
|
||||
|
||||
void texture::unbind()
|
||||
{
|
||||
_impl->unbind();
|
||||
}
|
||||
|
||||
bool texture::valid() const
|
||||
{
|
||||
return _impl->valid();
|
||||
}
|
||||
|
||||
void texture::set_shape(data_layout s)
|
||||
{
|
||||
_shape = s;
|
||||
_shape = s;
|
||||
}
|
||||
|
||||
void texture::set_wrap(wrap_mode w)
|
||||
{
|
||||
_wrap = w;
|
||||
_wrap = w;
|
||||
}
|
||||
|
||||
uint32_t texture::native_handle() const
|
||||
{
|
||||
return _impl->_texture_id;
|
||||
return _impl->_texture_id;
|
||||
}
|
||||
|
||||
uint32_t texture::native_sampler_handle() const
|
||||
{
|
||||
return _impl->_texture_sampler;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue