inching slowly towards a renderer

This commit is contained in:
Hartmut Seichter 2019-01-11 23:21:09 +01:00
parent 4b695ecaf6
commit c7c7d5af77
28 changed files with 613 additions and 59 deletions

View file

@ -5,6 +5,9 @@ cmake_minimum_required(VERSION 3.8)
project(pixwerx)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/etc/cmake")
set (CMAKE_CXX_STANDARD 17)
add_subdirectory(src)
add_subdirectory(share)

View file

@ -0,0 +1,51 @@
# - Find mkdocs
# This module finds if mkdocs is installed. This code sets the following
# variables:
#
# MKDOCS_EXECUTABLE = full path to the mkdocs binary
#
# Copyright (c) 2015 Marcel Bollmann <bollmann@linguistics.rub.de>
# based on FindPHP5.cmake by Mathieu Malaterre, found at
# <https://github.com/malaterre/GDCM/>
#
find_program(MKDOCS_EXECUTABLE mkdocs)
if(MKDOCS_EXECUTABLE)
execute_process(COMMAND ${MKDOCS_EXECUTABLE} --version
RESULT_VARIABLE res
OUTPUT_VARIABLE var
ERROR_VARIABLE var
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_STRIP_TRAILING_WHITESPACE)
if(res)
if(${mkdocs_FIND_REQUIRED})
message(FATAL_ERROR "Error executing mkdocs --version")
elseif(NOT mkdocs_FIND_QUIETLY)
message(WARNING "Warning, could not run mkdocs --version")
endif()
else()
if(var MATCHES ".*mkdocs, version [0-9]+\\.[0-9]+\\.[0-9_.]+.*")
string(REGEX REPLACE ".*mkdocs, version ([0-9]+\\.[0-9]+\\.[0-9_.]+).*"
"\\1" MKDOCS_VERSION_STRING "${var}")
else()
if(NOT mkdocs_FIND_QUIETLY)
message(WARNING "regex not supported: {$var}.")
endif()
endif()
string( REGEX REPLACE "([0-9]+).*" "\\1" MKDOCS_VERSION_MAJOR "${MKDOCS_VERSION_STRING}" )
string( REGEX REPLACE "[0-9]+\\.([0-9]+).*" "\\1" MKDOCS_VERSION_MINOR "${MKDOCS_VERSION_STRING}" )
string( REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" MKDOCS_VERSION_PATCH "${MKDOCS_VERSION_STRING}" )
set(MKDOCS_VERSION ${MKDOCS_VERSION_MAJOR}.${MKDOCS_VERSION_MINOR}.${MKDOCS_VERSION_PATCH})
endif()
endif()
mark_as_advanced(
MKDOCS_EXECUTABLE
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(mkdocs
REQUIRED_VARS MKDOCS_EXECUTABLE
VERSION_VAR MKDOCS_VERSION)

20
share/CMakeLists.txt Normal file
View file

@ -0,0 +1,20 @@
find_package(mkdocs 1.0)
# if(MKDOCS_FOUND)
# configure_file(mkdocs.yml "${CMAKE_CURRENT_BINARY_DIR}/mkdocs.yml" COPYONLY)
# set(MKDOCS_FLAGS
# --site-dir "${CMAKE_CURRENT_BINARY_DIR}/docs/user/"
# --config-file "${CMAKE_CURRENT_BINARY_DIR}/mkdocs.yml"
# )
# if(DEBUG_MODE)
# list(APPEND MKDOCS_FLAGS --clean --verbose)
# endif()
# add_custom_target(docs-user
# ${MKDOCS_EXECUTABLE} build ${MKDOCS_FLAGS}
# WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
# COMMENT "Generating user documentation"
# )
# add_dependencies(docs docs-user)
# else()
# message(STATUS "SKIPPING generation of user documentation (mkdocs not found)")
# endif()

17
share/docs/index.md Normal file
View file

@ -0,0 +1,17 @@
# Welcome to MkDocs
For full documentation visit [mkdocs.org](https://mkdocs.org).
## Commands
* `mkdocs new [dir-name]` - Create a new project.
* `mkdocs serve` - Start the live-reloading docs server.
* `mkdocs build` - Build the documentation site.
* `mkdocs help` - Print this help message.
## Project layout
mkdocs.yml # The configuration file.
docs/
index.md # The documentation homepage.
... # Other markdown pages, images and other files.

1
share/mkdocs.yml Normal file
View file

@ -0,0 +1 @@
site_name: pixwerx engine

View file

@ -7,6 +7,6 @@ add_subdirectory(system)
#add_subdirectory(ui)
add_subdirectory(scripting)
add_subdirectory(visual)
add_subdirectory(geometry)
add_subdirectory(engine)

View file

@ -2,6 +2,7 @@
set(hdrs
include/pw/core/debug.hpp
include/pw/core/axisangle.hpp
# include/pw/core/buffer.hpp
include/pw/core/core.hpp
include/pw/core/math.hpp
include/pw/core/matrixbase.hpp
@ -13,12 +14,15 @@ set(hdrs
include/pw/core/point.hpp
include/pw/core/size.hpp
include/pw/core/timer.hpp
include/pw/core/mesh.hpp
include/pw/core/globals.hpp
)
set(srcs
src/buffer.cpp
src/image.cpp
src/debug.cpp
src/mesh.cpp
src/core.cpp
src/serialize.cpp
src/timer.cpp

View file

@ -1,4 +1,11 @@
#ifndef BUFFER_HPP
#define BUFFER_HPP
#ifndef PW_CORE_BUFFER_HPP
#define PW_CORE_BUFFER_HPP
#endif // BUFFER_HPP
#include <pw/core/globals.hpp>
#include <vector>
#endif // PW_CORE_BUFFER_HPP

View file

@ -6,18 +6,21 @@
namespace pw {
const static double __PW_PI = 3.1415926535897932384626433832795028841971693993751058209;
const static double __RAD2DEG = 180.0 / __PW_PI;
const static double __DEG2RAD = __PW_PI / 180.0;
template <typename T>
inline const T pi() { return static_cast<T>(__PW_PI); }
template <typename T>
inline static double rad_to_deg(const T& angle_in_radian) {
return static_cast<T>(angle_in_radian * T(180.) / pi<T>());
inline static T rad_to_deg(const T& angle_in_radian) {
return angle_in_radian * __RAD2DEG;
}
template <typename T>
inline static double deg_to_rad(const T& angle_in_degree) {
return static_cast<T>(angle_in_degree * pi<T>() / T(180.));
inline static T deg_to_rad(const T& angle_in_degree) {
return angle_in_degree * __DEG2RAD;
}
}

View file

@ -1,17 +1,17 @@
#ifndef PW_SCENE_MESH_HPP
#define PW_SCENE_MESH_HPP
#ifndef PW_CORE_MESH_HPP
#define PW_CORE_MESH_HPP
#include <pw/core/matrix.hpp>
#include <pw/scene/component.hpp>
#include <pw/core/globals.hpp>
#include <pw/core/vector.hpp>
namespace pw {
class mesh : public component {
class mesh {
public:
using component::component;
typedef std::vector<int32_t> index_t;
typedef std::vector<float> vertex_t;
typedef std::vector<int32_t> indexarray_t;
typedef std::vector<vector3> vertex3array_t;
typedef std::vector<vector2> vertex2array_t;
enum topology_type {
triangles,
@ -23,20 +23,24 @@ public:
points
};
void set_indices(const indexarray_t& v) { _indices = v; }
void set_vertices(const vertex3array_t& v) { _vertices = v; }
const indexarray_t& indices() const { return _indices; }
const vertex3array_t& vertices() const { return _vertices; }
void reset();
protected:
// index data
// vertex d ata
// normal data
// color data
// uv data
// tangents data
// boundary
indexarray_t _indices; //!< indices according to topology type
vertex3array_t _vertices; //!< geometry data
vertex3array_t _normals; //!< normal data
vertex3array_t _colors; //!< color data
std::vector<vertex2array_t> _uvs; //!< storing multiple UV sets
// TODO add weights, tangents etc. pp.
};
}

5
src/core/src/buffer.cpp Normal file
View file

@ -0,0 +1,5 @@
#include "pw/core/buffer.hpp"
namespace pw {
}

View file

@ -1,9 +1,8 @@
#include "pw/scene/mesh.hpp"
#include "pw/core/mesh.hpp"
namespace pw {
}

View file

@ -1,5 +1,12 @@
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "Build the GLFW example programs" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "Build the GLFW test programs" FORCE)
set(GLFW_BUILD_DOCS OFF CACHE BOOL "Build the GLFW documentation" FORCE)
set(GLFW_INSTALL OFF CACHE BOOL "Generate installation target" FORCE)
add_subdirectory(glfw-3.2.1)
add_subdirectory(lua-5.3.5)
add_subdirectory(glad)
#add_subdirectory(arrrgh)

View file

@ -1,4 +1,11 @@
cmake_minimum_required(VERSION 3.8)
project(glad)
add_subdirectory(src)
add_library(glad STATIC src/glad.c)
target_include_directories(
glad
PUBLIC
include
)

View file

@ -1,3 +0,0 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include)
add_library(glad STATIC glad.c)

View file

@ -0,0 +1,29 @@
set(hdrs
include/pw/geometry/primitives.hpp
)
set(srcs
src/primitives.cpp
)
add_library(pwgeometry
STATIC
${hdrs}
${srcs}
)
target_include_directories(
pwgeometry
PUBLIC
include
)
target_include_directories(
pwgeometry
PUBLIC
)
target_link_libraries(pwgeometry pwcore)
#add_subdirectory(tests)

View file

@ -0,0 +1,21 @@
#ifndef PW_GEOMETRY_PRIMITIVES_HPP
#define PW_GEOMETRY_PRIMITIVES_HPP
#include <pw/core/mesh.hpp>
namespace pw {
struct primitives {
static mesh box(real_t size_x, real_t size_y, real_t size_z);
static mesh sphere(real_t radius,int divisions_latitude,int divisions_longitude);
static mesh cone();
static mesh pyramid();
};
};
#endif

View file

View file

@ -0,0 +1,87 @@
#include "pw/geometry/primitives.hpp"
namespace pw {
mesh primitives::box(real_t size_x,real_t size_y, real_t size_z)
{
mesh m;
mesh::vertex3array_t vertices;
vertices.push_back(vector3(-size_x / 2,-size_y / 2, size_z / 2)); // 0
vertices.push_back(vector3( size_x / 2,-size_y / 2, size_z / 2)); // 1
vertices.push_back(vector3( size_x / 2, size_y / 2, size_z / 2)); // 2
vertices.push_back(vector3(-size_x / 2, size_y / 2, size_z / 2)); // 3
vertices.push_back(vector3(-size_x / 2,-size_y / 2,-size_z / 2)); // 4
vertices.push_back(vector3( size_x / 2,-size_y / 2,-size_z / 2)); // 5
vertices.push_back(vector3( size_x / 2, size_y / 2,-size_z / 2)); // 6
vertices.push_back(vector3(-size_x / 2, size_y / 2,-size_z / 2)); // 7
mesh::indexarray_t indices = {
0, 1, 2, // 0
2, 3, 0, // 1
1, 5, 6, // 2
6, 2, 1, // 3
5, 4, 7, // 4
7, 6, 5, // 5
4, 0, 3, // 6
3, 7, 4, // 7
3, 2, 6, // 8
6, 7, 3, // 9
4, 5, 1, // 10
1, 0, 4 // 11
};
m.set_indices(indices);
return m;
}
mesh primitives::sphere(real_t radius,int divisions_latitude,int divisions_longitude)
{
using std::cos;
using std::sin;
const real_t _division_lat = real_t(360.0) / divisions_latitude;
const real_t _division_lon = real_t(360.0) / divisions_longitude;
// res = new tpPrimitive(tpPrimitive::kTriangleStrip);
//res->setPrimitiveType(tpPrimitive::kLineStrip);
// real_t _latitude, _longitude;
real_t dToR;
real_t x, y, z;
for (real_t _latitude = 0; _latitude < 360; _latitude += _division_lat)
{
for (real_t _longitude = 0; _longitude < 360; _longitude += _division_lon)
{
x = sin ( deg_to_rad(_longitude) ) * cos ( (_latitude + _division_lat) );
y = sin ( deg_to_rad(_latitude + _division_lat) );
z = cos ( deg_to_rad(_longitude) * cos ( deg_to_rad(_latitude + _division_lat) ) );
// assign the second normal and vertex
// res->addVertexNormal(tpVec3r(x * radius,y * radius,z * radius),
// tpVec3r(x,y,z)
// );
// calculate the coordinates
x = sin ( deg_to_rad(_longitude) ) * cos (deg_to_rad(_latitude) );
y = sin ( deg_to_rad(_latitude) );
z = cos ( deg_to_rad(_longitude) ) * cos (deg_to_rad(_latitude) );
// assign a normal and a vertex
// res->addVertexNormal(
// tpVec3r(x * radius,y * radius,z * radius),
// tpVec3r(x,y,z)
// );
}
}
}
}

View file

@ -3,7 +3,7 @@ set(hdrs
include/pw/scene/camera.hpp
include/pw/scene/component.hpp
include/pw/scene/node.hpp
include/pw/scene/mesh.hpp
# include/pw/scene/mesh.hpp
include/pw/scene/scene.hpp
include/pw/scene/transform.hpp
include/pw/scene/traverser.hpp
@ -13,7 +13,7 @@ set(srcs
src/node.cpp
src/camera.cpp
src/component.cpp
src/mesh.cpp
# src/mesh.cpp
src/scene.cpp
src/transform.cpp
src/traverser.cpp

View file

@ -62,8 +62,8 @@ protected:
real_t _ortho_size = 2;
private:
matrix4x4 _projection;
};

View file

@ -78,11 +78,9 @@ do
if (pw.input:get().mouse_button == 1) then
print(pw.input:get().mouse_position.x,pw.input:get().mouse_position.y)
-- w.fullscreen = not w.fullscreen
-- w.fullscreen = not w.fullscreen
end
-- print("update")
end

View file

@ -1,25 +1,25 @@
set(hdrs
include/pw/system/window.hpp
include/pw/system/input.hpp
)
include/pw/system/window.hpp
include/pw/system/input.hpp
)
set(srcs
src/window.cpp
src/input.cpp
)
src/window.cpp
src/input.cpp
)
add_library(pwsystem
STATIC
${hdrs}
${srcs}
)
STATIC
${hdrs}
${srcs}
)
target_include_directories(
pwsystem
PUBLIC
include
)
pwsystem
PUBLIC
include
)
target_link_libraries(pwsystem pwcore pwvisual glfw glad)

View file

@ -1,11 +1,13 @@
set(hdrs
include/pw/visual/renderer.hpp
include/pw/visual/shader.hpp
include/pw/visual/context.hpp
)
set(srcs
src/renderer.cpp
src/shader.cpp
src/context.cpp
)
@ -21,6 +23,6 @@ target_include_directories(
include
)
target_link_libraries(pwvisual pwscene)
target_link_libraries(pwvisual pwscene glad)
#add_subdirectory(tests)

View file

@ -1,15 +1,29 @@
#ifndef PW_VISUAL_RENDERER_HPP
#define PW_VISUAL_RENDERER_HPP
#include <pw/scene/component.hpp>
//#include <pw/scene/component.hpp>
//#include <pw/scene/camera.hpp>
#include <pw/core/matrix.hpp>
#include <pw/core/mesh.hpp>
#include <map>
namespace pw {
class context;
class renderer {
public:
void render(context& context);
void render(const mesh& mesh,
const matrix4x4& model_matrix,
const matrix4x4& view_matrix,
const matrix4x4& projection_matrix
);
protected:
struct impl;
std::unique_ptr<impl> _impl;
};

View file

@ -0,0 +1,41 @@
#ifndef PW_VISUAL_SHADER_HPP
#define PW_VISUAL_SHADER_HPP
#include <pw/core/globals.hpp>
#include <pw/core/matrix.hpp>
#include <map>
namespace pw {
class shader {
public:
shader();
enum code_type {
vertex, //<
fragment,
geometry,
compute
};
void set_source(const std::string& c,code_type t);
std::string source(code_type t) { return _source[t]; }
// void set_attributes(const std::vector<std::string> > &attributes);
bool ready() const;
protected:
std::map<code_type,std::string> _source;
struct impl;
std::unique_ptr<impl> _impl;
};
}
#endif

View file

@ -1,9 +1,69 @@
#include "pw/visual/renderer.hpp"
#include "pw/core/mesh.hpp"
#include "glad/glad.h"
namespace pw {
void renderer::render(pw::context &context)
{
}
struct renderer::impl {
GLuint _vao = 0;
std::vector<GLuint> _vbos;
impl(renderer& )
{
}
void create(std::shared_ptr<mesh> mesh)
{
glGenVertexArrays(1,&_vao);
glBindVertexArray(_vao);
size_t arrays_needed = 0;
// should bail out here
if (!mesh->vertices().empty()) arrays_needed++;
if (!mesh->indices().empty()) arrays_needed++;
// TODO: implement the other arrays
_vbos.resize(arrays_needed);
glGenBuffers(_vbos.size(), _vbos.data());
// vertices
glBindBuffer(GL_ARRAY_BUFFER, _vbos[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(mesh->vertices().front()) * mesh->vertices().size(), mesh->vertices().data(),
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
// indices
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbos[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(mesh->indices().front()) * mesh->indices().size(), mesh->indices().data(),
GL_STATIC_DRAW);
// stop binding
glBindVertexArray(0);
}
void destroy()
{
glDeleteVertexArrays(1,&_vao);
for (auto vbo : _vbos)
glDeleteBuffers(1,&vbo);
_vbos.clear();
}
};
//pipeline > n*pass
//compositor
// render to fbo >
}

177
src/visual/src/shader.cpp Normal file
View file

@ -0,0 +1,177 @@
#include "pw/visual/shader.hpp"
#include "pw/core/debug.hpp"
#include "glad/glad.h"
namespace pw {
// TODO: move this to a separate implementation
struct shader::impl
{
shader& _shader;
GLuint _shader_program;
std::vector<GLuint> _shader_stages;
impl(shader& s)
: _shader(s)
{
}
~impl()
{
clear();
}
bool is_valid()
{
return glIsProgram(_shader_program);
}
void build()
{
for (auto s : _shader._source)
{
GLuint shader_type = 0;
switch (s.first) {
case shader::vertex:
shader_type = GL_VERTEX_SHADER;
break;
case shader::compute:
shader_type = GL_COMPUTE_SHADER;
break;
case shader::geometry:
shader_type = GL_GEOMETRY_SHADER;
break;
case shader::fragment:
shader_type = GL_FRAGMENT_SHADER;
break;
}
GLuint shaderId = glCreateShader(shader_type);
char* src = const_cast<char*>(s.second.c_str());
GLint size = static_cast<GLint>(s.second.length());
glShaderSource(shaderId , 1, &src, &size);
glCompileShader(shaderId);
GLint is_compiled = GL_FALSE;
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &is_compiled);
if(is_compiled == GL_FALSE)
{
GLint log_length;
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &log_length);
char* log_buffer = new char[log_length];
glGetShaderInfoLog(shaderId, log_length, &log_length, log_buffer);
// TODO - handle errors!
std::string info_log_string(log_buffer);
delete [] log_buffer;
debug::e() << info_log_string;
break;
}
_shader_stages.push_back(shaderId);
}
_shader_program = glCreateProgram();
for (auto s : _shader_stages)
glAttachShader(_shader_program,s);
// attribute binding ...
/* Bind attribute index 0 (coordinates) to in_Position and attribute index 1 (color) to in_Color */
/* Attribute locations must be setup before calling glLinkProgram. */
// glBindAttribLocation(shaderprogram, 0, "in_Position");
// glBindAttribLocation(shaderprogram, 1, "in_Color");
glLinkProgram(_shader_program);
GLint is_linked = 0;
glGetProgramiv(_shader_program, GL_LINK_STATUS, &is_linked);
if(is_linked == GL_FALSE)
{
GLint log_length;
/* Noticed that glGetProgramiv is used to get the length for a shader program, not glGetShaderiv. */
glGetProgramiv(_shader_program, GL_INFO_LOG_LENGTH, &log_length);
/* The maxLength includes the NULL character */
char* info_log = new char[log_length];
/* Notice that glGetProgramInfoLog, not glGetShaderInfoLog. */
glGetProgramInfoLog(_shader_program, log_length, &log_length, info_log);
std::string info_log_string;
debug::e() << info_log_string;
/* Handle the error in an appropriate way such as displaying a message or writing to a log file. */
/* In this simple program, we'll just leave */
delete [] info_log;
return;
}
}
void use()
{
glUseProgram(_shader_program);
}
void clear()
{
if (is_valid()) {
glDeleteProgram(_shader_program);
for (auto s : _shader_stages)
{
glDeleteShader(s);
}
}
}
void set_uniform(const std::string& name,const matrix4x4f& m)
{
GLint l = glGetUniformLocation(_shader_program,name.c_str());
glUniformMatrix4fv(l,1,GL_FALSE,m.data()); // TODO transpose?
}
};
shader::shader()
{
_impl = make_unique<impl>(*this);
}
bool shader::ready() const
{
return _impl->is_valid();
}
}