a working version with no error but still some bugs around texturing

This commit is contained in:
Hartmut Seichter 2021-01-28 20:11:17 +01:00
parent 2d8244386a
commit 68d4610470
16 changed files with 473 additions and 110 deletions

View file

@ -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)
,"generate_noise",&image::generate_noise
,"change_count",sol::property(&image::change_count,&image::set_change_count)
).new_enum<false>("layout"
);
image_type.create_named("pixel_layout"
,"rgb8", image::RGB8
,"rgb32", image::RGBA8
,"gray", image::LUM);
,"gray", image::LUM
);
// image_type["layout"] = lua.create_table_with(
// "rgb8", image::RGB8
// ,"rgb32", image::RGBA8
// ,"gray", image::LUM);
ns.new_usertype<rectangle>("rectangle"

View file

@ -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
);
}

View file

@ -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;

View file

@ -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();

View file

@ -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

View 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

View file

@ -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;
};

View file

@ -19,7 +19,7 @@
#endif
// Why? LLVM does not adhere to C++17
//#include <filesystem>
#include <filesystem>
namespace pw {

View file

@ -51,6 +51,8 @@ public:
void clear();
u_int32_t get_error() const;
protected:
struct impl;
std::unique_ptr<impl> _impl;

View file

@ -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:

View file

@ -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);

View file

@ -33,16 +33,10 @@ 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);
data_layout shape() const { return _shape; }
@ -50,12 +44,17 @@ public:
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;

View file

@ -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();
}
}

View file

@ -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::)

View file

@ -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);
@ -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());
}
};
@ -198,10 +211,22 @@ bool shader::ready() const
}
shader &shader::set_uniform_at_location(int location, float v)
{
_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();

View file

@ -2,6 +2,8 @@
#include "glad/glad.h"
#include <limits>
namespace pw {
@ -9,8 +11,9 @@ struct texture::impl {
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;
@ -24,67 +27,101 @@ 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();
// debug::d() << "\t" << " _texture_id " << _texture_id;
// debug::d() << "\t" << "_texture_sampler " << _texture_sampler;
// get errors
auto error = glGetError();
if (error != GL_NO_ERROR) {
debug::e() << __PRETTY_FUNCTION__ << " " << __LINE__ << " GL error: " << error;
return false;
}
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());
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);
return true;
}
@ -106,24 +143,39 @@ 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();
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)
@ -141,9 +193,5 @@ uint32_t texture::native_handle() const
return _impl->_texture_id;
}
uint32_t texture::native_sampler_handle() const
{
return _impl->_texture_sampler;
}
}