From eb03b86c5570b062dfd28c8080598ba5b82dea27 Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Sat, 17 Mar 2018 23:17:16 +0100 Subject: [PATCH 01/16] Remove picojson (no longer used) --- include/picojson.h | 1160 -------------------------------------------- 1 file changed, 1160 deletions(-) delete mode 100644 include/picojson.h diff --git a/include/picojson.h b/include/picojson.h deleted file mode 100644 index c4590dee..00000000 --- a/include/picojson.h +++ /dev/null @@ -1,1160 +0,0 @@ -/* - * Copyright 2009-2010 Cybozu Labs, Inc. - * Copyright 2011-2014 Kazuho Oku - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef picojson_h -#define picojson_h - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// for isnan/isinf -#if __cplusplus >= 201103L -#include -#else -extern "C" { -#ifdef _MSC_VER -#include -#elif defined(__INTEL_COMPILER) -#include -#else -#include -#endif -} -#endif - -#ifndef PICOJSON_USE_RVALUE_REFERENCE -#if (defined(__cpp_rvalue_references) && __cpp_rvalue_references >= 200610) || (defined(_MSC_VER) && _MSC_VER >= 1600) -#define PICOJSON_USE_RVALUE_REFERENCE 1 -#else -#define PICOJSON_USE_RVALUE_REFERENCE 0 -#endif -#endif // PICOJSON_USE_RVALUE_REFERENCE - -// experimental support for int64_t (see README.mkdn for detail) -#ifdef PICOJSON_USE_INT64 -#define __STDC_FORMAT_MACROS -#include -#include -#endif - -// to disable the use of localeconv(3), set PICOJSON_USE_LOCALE to 0 -#ifndef PICOJSON_USE_LOCALE -#define PICOJSON_USE_LOCALE 1 -#endif -#if PICOJSON_USE_LOCALE -extern "C" { -#include -} -#endif - -#ifndef PICOJSON_ASSERT -#define PICOJSON_ASSERT(e) \ - do { \ - if (!(e)) \ - throw std::runtime_error(#e); \ - } while (0) -#endif - -#ifdef _MSC_VER -#define SNPRINTF _snprintf_s -#pragma warning(push) -#pragma warning(disable : 4244) // conversion from int to char -#pragma warning(disable : 4127) // conditional expression is constant -#pragma warning(disable : 4702) // unreachable code -#else -#define SNPRINTF snprintf -#endif - -namespace picojson { - - enum { - null_type, - boolean_type, - number_type, - string_type, - array_type, - object_type -#ifdef PICOJSON_USE_INT64 - , - int64_type -#endif - }; - - enum { INDENT_WIDTH = 2 }; - - struct null {}; - - class value { - public: - typedef std::vector array; - typedef std::map object; - union _storage { - bool boolean_; - double number_; -#ifdef PICOJSON_USE_INT64 - int64_t int64_; -#endif - std::string *string_; - array *array_; - object *object_; - }; - - protected: - int type_; - _storage u_; - - public: - value(); - value(int type, bool); - explicit value(bool b); -#ifdef PICOJSON_USE_INT64 - explicit value(int64_t i); -#endif - explicit value(double n); - explicit value(const std::string &s); - explicit value(const array &a); - explicit value(const object &o); -#if PICOJSON_USE_RVALUE_REFERENCE - explicit value(std::string &&s); - explicit value(array &&a); - explicit value(object &&o); -#endif - explicit value(const char *s); - value(const char *s, size_t len); - ~value(); - value(const value &x); - value &operator=(const value &x); -#if PICOJSON_USE_RVALUE_REFERENCE - value(value &&x) throw(); - value &operator=(value &&x) throw(); -#endif - void swap(value &x) throw(); - template bool is() const; - template const T &get() const; - template T &get(); - template void set(const T &); -#if PICOJSON_USE_RVALUE_REFERENCE - template void set(T &&); -#endif - bool evaluate_as_boolean() const; - const value &get(const size_t idx) const; - const value &get(const std::string &key) const; - value &get(const size_t idx); - value &get(const std::string &key); - - bool contains(const size_t idx) const; - bool contains(const std::string &key) const; - std::string to_str() const; - template void serialize(Iter os, bool prettify = false) const; - std::string serialize(bool prettify = false) const; - - private: - template value(const T *); // intentionally defined to block implicit conversion of pointer to bool - template static void _indent(Iter os, int indent); - template void _serialize(Iter os, int indent) const; - std::string _serialize(int indent) const; - void clear(); - }; - - typedef value::array array; - typedef value::object object; - - inline value::value() : type_(null_type), u_() { - } - - inline value::value(int type, bool) : type_(type), u_() { - switch (type) { -#define INIT(p, v) \ - case p##type: \ - u_.p = v; \ - break - INIT(boolean_, false); - INIT(number_, 0.0); -#ifdef PICOJSON_USE_INT64 - INIT(int64_, 0); -#endif - INIT(string_, new std::string()); - INIT(array_, new array()); - INIT(object_, new object()); -#undef INIT - default: - break; - } - } - - inline value::value(bool b) : type_(boolean_type), u_() { - u_.boolean_ = b; - } - -#ifdef PICOJSON_USE_INT64 - inline value::value(int64_t i) : type_(int64_type), u_() { - u_.int64_ = i; -} -#endif - - inline value::value(double n) : type_(number_type), u_() { - if ( -#ifdef _MSC_VER -!_finite(n) -#elif __cplusplus >= 201103L || !(defined(isnan) && defined(isinf)) -std::isnan(n) || std::isinf(n) -#else - isnan(n) || isinf(n) -#endif - ) { - throw std::overflow_error(""); - } - u_.number_ = n; - } - - inline value::value(const std::string &s) : type_(string_type), u_() { - u_.string_ = new std::string(s); - } - - inline value::value(const array &a) : type_(array_type), u_() { - u_.array_ = new array(a); - } - - inline value::value(const object &o) : type_(object_type), u_() { - u_.object_ = new object(o); - } - -#if PICOJSON_USE_RVALUE_REFERENCE - inline value::value(std::string &&s) : type_(string_type), u_() { - u_.string_ = new std::string(std::move(s)); - } - - inline value::value(array &&a) : type_(array_type), u_() { - u_.array_ = new array(std::move(a)); - } - - inline value::value(object &&o) : type_(object_type), u_() { - u_.object_ = new object(std::move(o)); - } -#endif - - inline value::value(const char *s) : type_(string_type), u_() { - u_.string_ = new std::string(s); - } - - inline value::value(const char *s, size_t len) : type_(string_type), u_() { - u_.string_ = new std::string(s, len); - } - - inline void value::clear() { - switch (type_) { -#define DEINIT(p) \ - case p##type: \ - delete u_.p; \ - break - DEINIT(string_); - DEINIT(array_); - DEINIT(object_); -#undef DEINIT - default: - break; - } - } - - inline value::~value() { - clear(); - } - - inline value::value(const value &x) : type_(x.type_), u_() { - switch (type_) { -#define INIT(p, v) \ - case p##type: \ - u_.p = v; \ - break - INIT(string_, new std::string(*x.u_.string_)); - INIT(array_, new array(*x.u_.array_)); - INIT(object_, new object(*x.u_.object_)); -#undef INIT - default: - u_ = x.u_; - break; - } - } - - inline value &value::operator=(const value &x) { - if (this != &x) { - value t(x); - swap(t); - } - return *this; - } - -#if PICOJSON_USE_RVALUE_REFERENCE - inline value::value(value &&x) throw() : type_(null_type), u_() { - swap(x); - } - inline value &value::operator=(value &&x) throw() { - swap(x); - return *this; - } -#endif - inline void value::swap(value &x) throw() { - std::swap(type_, x.type_); - std::swap(u_, x.u_); - } - -#define IS(ctype, jtype) \ - template <> inline bool value::is() const { \ - return type_ == jtype##_type; \ - } - IS(null, null) - IS(bool, boolean) -#ifdef PICOJSON_USE_INT64 - IS(int64_t, int64) -#endif - IS(std::string, string) - IS(array, array) - IS(object, object) -#undef IS - template <> inline bool value::is() const { - return type_ == number_type -#ifdef PICOJSON_USE_INT64 - || type_ == int64_type -#endif - ; - } - -#define GET(ctype, var) \ - template <> inline const ctype &value::get() const { \ - PICOJSON_ASSERT("type mismatch! call is() before get()" && is()); \ - return var; \ - } \ - template <> inline ctype &value::get() { \ - PICOJSON_ASSERT("type mismatch! call is() before get()" && is()); \ - return var; \ - } - GET(bool, u_.boolean_) - GET(std::string, *u_.string_) - GET(array, *u_.array_) - GET(object, *u_.object_) -#ifdef PICOJSON_USE_INT64 - GET(double, - (type_ == int64_type && (const_cast(this)->type_ = number_type, const_cast(this)->u_.number_ = u_.int64_), - u_.number_)) -GET(int64_t, u_.int64_) -#else - GET(double, u_.number_) -#endif -#undef GET - -#define SET(ctype, jtype, setter) \ - template <> inline void value::set(const ctype &_val) { \ - clear(); \ - type_ = jtype##_type; \ - setter \ - } - SET(bool, boolean, u_.boolean_ = _val;) - SET(std::string, string, u_.string_ = new std::string(_val);) - SET(array, array, u_.array_ = new array(_val);) - SET(object, object, u_.object_ = new object(_val);) - SET(double, number, u_.number_ = _val;) -#ifdef PICOJSON_USE_INT64 - SET(int64_t, int64, u_.int64_ = _val;) -#endif -#undef SET - -#if PICOJSON_USE_RVALUE_REFERENCE -#define MOVESET(ctype, jtype, setter) \ - template <> inline void value::set(ctype && _val) { \ - clear(); \ - type_ = jtype##_type; \ - setter \ - } - MOVESET(std::string, string, u_.string_ = new std::string(std::move(_val));) - MOVESET(array, array, u_.array_ = new array(std::move(_val));) - MOVESET(object, object, u_.object_ = new object(std::move(_val));) -#undef MOVESET -#endif - - inline bool value::evaluate_as_boolean() const { - switch (type_) { - case null_type: - return false; - case boolean_type: - return u_.boolean_; - case number_type: - return u_.number_ != 0; -#ifdef PICOJSON_USE_INT64 - case int64_type: - return u_.int64_ != 0; -#endif - case string_type: - return !u_.string_->empty(); - default: - return true; - } - } - - inline const value &value::get(const size_t idx) const { - static value s_null; - PICOJSON_ASSERT(is()); - return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; - } - - inline value &value::get(const size_t idx) { - static value s_null; - PICOJSON_ASSERT(is()); - return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; - } - - inline const value &value::get(const std::string &key) const { - static value s_null; - PICOJSON_ASSERT(is()); - object::const_iterator i = u_.object_->find(key); - return i != u_.object_->end() ? i->second : s_null; - } - - inline value &value::get(const std::string &key) { - static value s_null; - PICOJSON_ASSERT(is()); - object::iterator i = u_.object_->find(key); - return i != u_.object_->end() ? i->second : s_null; - } - - inline bool value::contains(const size_t idx) const { - PICOJSON_ASSERT(is()); - return idx < u_.array_->size(); - } - - inline bool value::contains(const std::string &key) const { - PICOJSON_ASSERT(is()); - object::const_iterator i = u_.object_->find(key); - return i != u_.object_->end(); - } - - inline std::string value::to_str() const { - switch (type_) { - case null_type: - return "null"; - case boolean_type: - return u_.boolean_ ? "true" : "false"; -#ifdef PICOJSON_USE_INT64 - case int64_type: { - char buf[sizeof("-9223372036854775808")]; - SNPRINTF(buf, sizeof(buf), "%" PRId64, u_.int64_); - return buf; - } -#endif - case number_type: { - char buf[256]; - double tmp; - SNPRINTF(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ? "%.f" : "%.17g", u_.number_); -#if PICOJSON_USE_LOCALE - char *decimal_point = localeconv()->decimal_point; - if (strcmp(decimal_point, ".") != 0) { - size_t decimal_point_len = strlen(decimal_point); - for (char *p = buf; *p != '\0'; ++p) { - if (strncmp(p, decimal_point, decimal_point_len) == 0) { - return std::string(buf, p) + "." + (p + decimal_point_len); - } - } - } -#endif - return buf; - } - case string_type: - return *u_.string_; - case array_type: - return "array"; - case object_type: - return "object"; - default: - PICOJSON_ASSERT(0); -#ifdef _MSC_VER - __assume(0); -#endif - } - return std::string(); - } - - template void copy(const std::string &s, Iter oi) { - std::copy(s.begin(), s.end(), oi); - } - - template struct serialize_str_char { - Iter oi; - void operator()(char c) { - switch (c) { -#define MAP(val, sym) \ - case val: \ - copy(sym, oi); \ - break - MAP('"', "\\\""); - MAP('\\', "\\\\"); - MAP('/', "\\/"); - MAP('\b', "\\b"); - MAP('\f', "\\f"); - MAP('\n', "\\n"); - MAP('\r', "\\r"); - MAP('\t', "\\t"); -#undef MAP - default: - if (static_cast(c) < 0x20 || c == 0x7f) { - char buf[7]; - SNPRINTF(buf, sizeof(buf), "\\u%04x", c & 0xff); - copy(buf, buf + 6, oi); - } else { - *oi++ = c; - } - break; - } - } - }; - - template void serialize_str(const std::string &s, Iter oi) { - *oi++ = '"'; - serialize_str_char process_char = {oi}; - std::for_each(s.begin(), s.end(), process_char); - *oi++ = '"'; - } - - template void value::serialize(Iter oi, bool prettify) const { - return _serialize(oi, prettify ? 0 : -1); - } - - inline std::string value::serialize(bool prettify) const { - return _serialize(prettify ? 0 : -1); - } - - template void value::_indent(Iter oi, int indent) { - *oi++ = '\n'; - for (int i = 0; i < indent * INDENT_WIDTH; ++i) { - *oi++ = ' '; - } - } - - template void value::_serialize(Iter oi, int indent) const { - switch (type_) { - case string_type: - serialize_str(*u_.string_, oi); - break; - case array_type: { - *oi++ = '['; - if (indent != -1) { - ++indent; - } - for (array::const_iterator i = u_.array_->begin(); i != u_.array_->end(); ++i) { - if (i != u_.array_->begin()) { - *oi++ = ','; - } - if (indent != -1) { - _indent(oi, indent); - } - i->_serialize(oi, indent); - } - if (indent != -1) { - --indent; - if (!u_.array_->empty()) { - _indent(oi, indent); - } - } - *oi++ = ']'; - break; - } - case object_type: { - *oi++ = '{'; - if (indent != -1) { - ++indent; - } - for (object::const_iterator i = u_.object_->begin(); i != u_.object_->end(); ++i) { - if (i != u_.object_->begin()) { - *oi++ = ','; - } - if (indent != -1) { - _indent(oi, indent); - } - serialize_str(i->first, oi); - *oi++ = ':'; - if (indent != -1) { - *oi++ = ' '; - } - i->second._serialize(oi, indent); - } - if (indent != -1) { - --indent; - if (!u_.object_->empty()) { - _indent(oi, indent); - } - } - *oi++ = '}'; - break; - } - default: - copy(to_str(), oi); - break; - } - if (indent == 0) { - *oi++ = '\n'; - } - } - - inline std::string value::_serialize(int indent) const { - std::string s; - _serialize(std::back_inserter(s), indent); - return s; - } - - template class input { - protected: - Iter cur_, end_; - bool consumed_; - int line_; - - public: - input(const Iter &first, const Iter &last) : cur_(first), end_(last), consumed_(false), line_(1) { - } - int getc() { - if (consumed_) { - if (*cur_ == '\n') { - ++line_; - } - ++cur_; - } - if (cur_ == end_) { - consumed_ = false; - return -1; - } - consumed_ = true; - return *cur_ & 0xff; - } - void ungetc() { - consumed_ = false; - } - Iter cur() const { - if (consumed_) { - input *self = const_cast *>(this); - self->consumed_ = false; - ++self->cur_; - } - return cur_; - } - int line() const { - return line_; - } - void skip_ws() { - while (1) { - int ch = getc(); - if (!(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) { - ungetc(); - break; - } - } - } - bool expect(const int expected) { - skip_ws(); - if (getc() != expected) { - ungetc(); - return false; - } - return true; - } - bool match(const std::string &pattern) { - for (std::string::const_iterator pi(pattern.begin()); pi != pattern.end(); ++pi) { - if (getc() != *pi) { - ungetc(); - return false; - } - } - return true; - } - }; - - template inline int _parse_quadhex(input &in) { - int uni_ch = 0, hex; - for (int i = 0; i < 4; i++) { - if ((hex = in.getc()) == -1) { - return -1; - } - if ('0' <= hex && hex <= '9') { - hex -= '0'; - } else if ('A' <= hex && hex <= 'F') { - hex -= 'A' - 0xa; - } else if ('a' <= hex && hex <= 'f') { - hex -= 'a' - 0xa; - } else { - in.ungetc(); - return -1; - } - uni_ch = uni_ch * 16 + hex; - } - return uni_ch; - } - - template inline bool _parse_codepoint(String &out, input &in) { - int uni_ch; - if ((uni_ch = _parse_quadhex(in)) == -1) { - return false; - } - if (0xd800 <= uni_ch && uni_ch <= 0xdfff) { - if (0xdc00 <= uni_ch) { - // a second 16-bit of a surrogate pair appeared - return false; - } - // first 16-bit of surrogate pair, get the next one - if (in.getc() != '\\' || in.getc() != 'u') { - in.ungetc(); - return false; - } - int second = _parse_quadhex(in); - if (!(0xdc00 <= second && second <= 0xdfff)) { - return false; - } - uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff); - uni_ch += 0x10000; - } - if (uni_ch < 0x80) { - out.push_back(static_cast(uni_ch)); - } else { - if (uni_ch < 0x800) { - out.push_back(static_cast(0xc0 | (uni_ch >> 6))); - } else { - if (uni_ch < 0x10000) { - out.push_back(static_cast(0xe0 | (uni_ch >> 12))); - } else { - out.push_back(static_cast(0xf0 | (uni_ch >> 18))); - out.push_back(static_cast(0x80 | ((uni_ch >> 12) & 0x3f))); - } - out.push_back(static_cast(0x80 | ((uni_ch >> 6) & 0x3f))); - } - out.push_back(static_cast(0x80 | (uni_ch & 0x3f))); - } - return true; - } - - template inline bool _parse_string(String &out, input &in) { - while (1) { - int ch = in.getc(); - if (ch < ' ') { - in.ungetc(); - return false; - } else if (ch == '"') { - return true; - } else if (ch == '\\') { - if ((ch = in.getc()) == -1) { - return false; - } - switch (ch) { -#define MAP(sym, val) \ - case sym: \ - out.push_back(val); \ - break - MAP('"', '\"'); - MAP('\\', '\\'); - MAP('/', '/'); - MAP('b', '\b'); - MAP('f', '\f'); - MAP('n', '\n'); - MAP('r', '\r'); - MAP('t', '\t'); -#undef MAP - case 'u': - if (!_parse_codepoint(out, in)) { - return false; - } - break; - default: - return false; - } - } else { - out.push_back(static_cast(ch)); - } - } - return false; - } - - template inline bool _parse_array(Context &ctx, input &in) { - if (!ctx.parse_array_start()) { - return false; - } - size_t idx = 0; - if (in.expect(']')) { - return ctx.parse_array_stop(idx); - } - do { - if (!ctx.parse_array_item(in, idx)) { - return false; - } - idx++; - } while (in.expect(',')); - return in.expect(']') && ctx.parse_array_stop(idx); - } - - template inline bool _parse_object(Context &ctx, input &in) { - if (!ctx.parse_object_start()) { - return false; - } - if (in.expect('}')) { - return true; - } - do { - std::string key; - if (!in.expect('"') || !_parse_string(key, in) || !in.expect(':')) { - return false; - } - if (!ctx.parse_object_item(in, key)) { - return false; - } - } while (in.expect(',')); - return in.expect('}'); - } - - template inline std::string _parse_number(input &in) { - std::string num_str; - while (1) { - int ch = in.getc(); - if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == 'e' || ch == 'E') { - num_str.push_back(static_cast(ch)); - } else if (ch == '.') { -#if PICOJSON_USE_LOCALE - num_str += localeconv()->decimal_point; -#else - num_str.push_back('.'); -#endif - } else { - in.ungetc(); - break; - } - } - return num_str; - } - - template inline bool _parse(Context &ctx, input &in) { - in.skip_ws(); - int ch = in.getc(); - switch (ch) { -#define IS(ch, text, op) \ - case ch: \ - if (in.match(text) && op) { \ - return true; \ - } else { \ - return false; \ - } - IS('n', "ull", ctx.set_null()); - IS('f', "alse", ctx.set_bool(false)); - IS('t', "rue", ctx.set_bool(true)); -#undef IS - case '"': - return ctx.parse_string(in); - case '[': - return _parse_array(ctx, in); - case '{': - return _parse_object(ctx, in); - default: - if (('0' <= ch && ch <= '9') || ch == '-') { - double f; - char *endp; - in.ungetc(); - std::string num_str(_parse_number(in)); - if (num_str.empty()) { - return false; - } -#ifdef PICOJSON_USE_INT64 - { - errno = 0; - intmax_t ival = strtoimax(num_str.c_str(), &endp, 10); - if (errno == 0 && std::numeric_limits::min() <= ival && ival <= std::numeric_limits::max() && - endp == num_str.c_str() + num_str.size()) { - ctx.set_int64(ival); - return true; - } - } -#endif - f = strtod(num_str.c_str(), &endp); - if (endp == num_str.c_str() + num_str.size()) { - ctx.set_number(f); - return true; - } - return false; - } - break; - } - in.ungetc(); - return false; - } - - class deny_parse_context { - public: - bool set_null() { - return false; - } - bool set_bool(bool) { - return false; - } -#ifdef PICOJSON_USE_INT64 - bool set_int64(int64_t) { - return false; - } -#endif - bool set_number(double) { - return false; - } - template bool parse_string(input &) { - return false; - } - bool parse_array_start() { - return false; - } - template bool parse_array_item(input &, size_t) { - return false; - } - bool parse_array_stop(size_t) { - return false; - } - bool parse_object_start() { - return false; - } - template bool parse_object_item(input &, const std::string &) { - return false; - } - }; - - class default_parse_context { - protected: - value *out_; - - public: - default_parse_context(value *out) : out_(out) { - } - bool set_null() { - *out_ = value(); - return true; - } - bool set_bool(bool b) { - *out_ = value(b); - return true; - } -#ifdef PICOJSON_USE_INT64 - bool set_int64(int64_t i) { - *out_ = value(i); - return true; - } -#endif - bool set_number(double f) { - *out_ = value(f); - return true; - } - template bool parse_string(input &in) { - *out_ = value(string_type, false); - return _parse_string(out_->get(), in); - } - bool parse_array_start() { - *out_ = value(array_type, false); - return true; - } - template bool parse_array_item(input &in, size_t) { - array &a = out_->get(); - a.push_back(value()); - default_parse_context ctx(&a.back()); - return _parse(ctx, in); - } - bool parse_array_stop(size_t) { - return true; - } - bool parse_object_start() { - *out_ = value(object_type, false); - return true; - } - template bool parse_object_item(input &in, const std::string &key) { - object &o = out_->get(); - default_parse_context ctx(&o[key]); - return _parse(ctx, in); - } - - private: - default_parse_context(const default_parse_context &); - default_parse_context &operator=(const default_parse_context &); - }; - - class null_parse_context { - public: - struct dummy_str { - void push_back(int) { - } - }; - - public: - null_parse_context() { - } - bool set_null() { - return true; - } - bool set_bool(bool) { - return true; - } -#ifdef PICOJSON_USE_INT64 - bool set_int64(int64_t) { - return true; - } -#endif - bool set_number(double) { - return true; - } - template bool parse_string(input &in) { - dummy_str s; - return _parse_string(s, in); - } - bool parse_array_start() { - return true; - } - template bool parse_array_item(input &in, size_t) { - return _parse(*this, in); - } - bool parse_array_stop(size_t) { - return true; - } - bool parse_object_start() { - return true; - } - template bool parse_object_item(input &in, const std::string &) { - return _parse(*this, in); - } - - private: - null_parse_context(const null_parse_context &); - null_parse_context &operator=(const null_parse_context &); - }; - -// obsolete, use the version below - template inline std::string parse(value &out, Iter &pos, const Iter &last) { - std::string err; - pos = parse(out, pos, last, &err); - return err; - } - - template inline Iter _parse(Context &ctx, const Iter &first, const Iter &last, std::string *err) { - input in(first, last); - if (!_parse(ctx, in) && err != NULL) { - char buf[64]; - SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line()); - *err = buf; - while (1) { - int ch = in.getc(); - if (ch == -1 || ch == '\n') { - break; - } else if (ch >= ' ') { - err->push_back(static_cast(ch)); - } - } - } - return in.cur(); - } - - template inline Iter parse(value &out, const Iter &first, const Iter &last, std::string *err) { - default_parse_context ctx(&out); - return _parse(ctx, first, last, err); - } - - inline std::string parse(value &out, const std::string &s) { - std::string err; - parse(out, s.begin(), s.end(), &err); - return err; - } - - inline std::string parse(value &out, std::istream &is) { - std::string err; - parse(out, std::istreambuf_iterator(is.rdbuf()), std::istreambuf_iterator(), &err); - return err; - } - - template struct last_error_t { static std::string s; }; - template std::string last_error_t::s; - - inline void set_last_error(const std::string &s) { - last_error_t::s = s; - } - - inline const std::string &get_last_error() { - return last_error_t::s; - } - - inline bool operator==(const value &x, const value &y) { - if (x.is()) - return y.is(); -#define PICOJSON_CMP(type) \ - if (x.is()) \ - return y.is() && x.get() == y.get() - PICOJSON_CMP(bool); - PICOJSON_CMP(double); - PICOJSON_CMP(std::string); - PICOJSON_CMP(array); - PICOJSON_CMP(object); -#undef PICOJSON_CMP - PICOJSON_ASSERT(0); -#ifdef _MSC_VER - __assume(0); -#endif - return false; - } - - inline bool operator!=(const value &x, const value &y) { - return !(x == y); - } -} - -#if !PICOJSON_USE_RVALUE_REFERENCE -namespace std { -template <> inline void swap(picojson::value &x, picojson::value &y) { - x.swap(y); -} -} -#endif - -inline std::istream &operator>>(std::istream &is, picojson::value &x) { - picojson::set_last_error(std::string()); - const std::string err(picojson::parse(x, is)); - if (!err.empty()) { - picojson::set_last_error(err); - is.setstate(std::ios::failbit); - } - return is; -} - -inline std::ostream &operator<<(std::ostream &os, const picojson::value &x) { - x.serialize(std::ostream_iterator(os)); - return os; -} -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#endif \ No newline at end of file From 2ea02bd9bd96552a905df764d3fde1ef61b67bf3 Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Sat, 17 Mar 2018 23:27:36 +0100 Subject: [PATCH 02/16] Revert "Remove picojson (no longer used)" This reverts commit eb03b86 --- include/picojson.h | 1160 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1160 insertions(+) create mode 100644 include/picojson.h diff --git a/include/picojson.h b/include/picojson.h new file mode 100644 index 00000000..c4590dee --- /dev/null +++ b/include/picojson.h @@ -0,0 +1,1160 @@ +/* + * Copyright 2009-2010 Cybozu Labs, Inc. + * Copyright 2011-2014 Kazuho Oku + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef picojson_h +#define picojson_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// for isnan/isinf +#if __cplusplus >= 201103L +#include +#else +extern "C" { +#ifdef _MSC_VER +#include +#elif defined(__INTEL_COMPILER) +#include +#else +#include +#endif +} +#endif + +#ifndef PICOJSON_USE_RVALUE_REFERENCE +#if (defined(__cpp_rvalue_references) && __cpp_rvalue_references >= 200610) || (defined(_MSC_VER) && _MSC_VER >= 1600) +#define PICOJSON_USE_RVALUE_REFERENCE 1 +#else +#define PICOJSON_USE_RVALUE_REFERENCE 0 +#endif +#endif // PICOJSON_USE_RVALUE_REFERENCE + +// experimental support for int64_t (see README.mkdn for detail) +#ifdef PICOJSON_USE_INT64 +#define __STDC_FORMAT_MACROS +#include +#include +#endif + +// to disable the use of localeconv(3), set PICOJSON_USE_LOCALE to 0 +#ifndef PICOJSON_USE_LOCALE +#define PICOJSON_USE_LOCALE 1 +#endif +#if PICOJSON_USE_LOCALE +extern "C" { +#include +} +#endif + +#ifndef PICOJSON_ASSERT +#define PICOJSON_ASSERT(e) \ + do { \ + if (!(e)) \ + throw std::runtime_error(#e); \ + } while (0) +#endif + +#ifdef _MSC_VER +#define SNPRINTF _snprintf_s +#pragma warning(push) +#pragma warning(disable : 4244) // conversion from int to char +#pragma warning(disable : 4127) // conditional expression is constant +#pragma warning(disable : 4702) // unreachable code +#else +#define SNPRINTF snprintf +#endif + +namespace picojson { + + enum { + null_type, + boolean_type, + number_type, + string_type, + array_type, + object_type +#ifdef PICOJSON_USE_INT64 + , + int64_type +#endif + }; + + enum { INDENT_WIDTH = 2 }; + + struct null {}; + + class value { + public: + typedef std::vector array; + typedef std::map object; + union _storage { + bool boolean_; + double number_; +#ifdef PICOJSON_USE_INT64 + int64_t int64_; +#endif + std::string *string_; + array *array_; + object *object_; + }; + + protected: + int type_; + _storage u_; + + public: + value(); + value(int type, bool); + explicit value(bool b); +#ifdef PICOJSON_USE_INT64 + explicit value(int64_t i); +#endif + explicit value(double n); + explicit value(const std::string &s); + explicit value(const array &a); + explicit value(const object &o); +#if PICOJSON_USE_RVALUE_REFERENCE + explicit value(std::string &&s); + explicit value(array &&a); + explicit value(object &&o); +#endif + explicit value(const char *s); + value(const char *s, size_t len); + ~value(); + value(const value &x); + value &operator=(const value &x); +#if PICOJSON_USE_RVALUE_REFERENCE + value(value &&x) throw(); + value &operator=(value &&x) throw(); +#endif + void swap(value &x) throw(); + template bool is() const; + template const T &get() const; + template T &get(); + template void set(const T &); +#if PICOJSON_USE_RVALUE_REFERENCE + template void set(T &&); +#endif + bool evaluate_as_boolean() const; + const value &get(const size_t idx) const; + const value &get(const std::string &key) const; + value &get(const size_t idx); + value &get(const std::string &key); + + bool contains(const size_t idx) const; + bool contains(const std::string &key) const; + std::string to_str() const; + template void serialize(Iter os, bool prettify = false) const; + std::string serialize(bool prettify = false) const; + + private: + template value(const T *); // intentionally defined to block implicit conversion of pointer to bool + template static void _indent(Iter os, int indent); + template void _serialize(Iter os, int indent) const; + std::string _serialize(int indent) const; + void clear(); + }; + + typedef value::array array; + typedef value::object object; + + inline value::value() : type_(null_type), u_() { + } + + inline value::value(int type, bool) : type_(type), u_() { + switch (type) { +#define INIT(p, v) \ + case p##type: \ + u_.p = v; \ + break + INIT(boolean_, false); + INIT(number_, 0.0); +#ifdef PICOJSON_USE_INT64 + INIT(int64_, 0); +#endif + INIT(string_, new std::string()); + INIT(array_, new array()); + INIT(object_, new object()); +#undef INIT + default: + break; + } + } + + inline value::value(bool b) : type_(boolean_type), u_() { + u_.boolean_ = b; + } + +#ifdef PICOJSON_USE_INT64 + inline value::value(int64_t i) : type_(int64_type), u_() { + u_.int64_ = i; +} +#endif + + inline value::value(double n) : type_(number_type), u_() { + if ( +#ifdef _MSC_VER +!_finite(n) +#elif __cplusplus >= 201103L || !(defined(isnan) && defined(isinf)) +std::isnan(n) || std::isinf(n) +#else + isnan(n) || isinf(n) +#endif + ) { + throw std::overflow_error(""); + } + u_.number_ = n; + } + + inline value::value(const std::string &s) : type_(string_type), u_() { + u_.string_ = new std::string(s); + } + + inline value::value(const array &a) : type_(array_type), u_() { + u_.array_ = new array(a); + } + + inline value::value(const object &o) : type_(object_type), u_() { + u_.object_ = new object(o); + } + +#if PICOJSON_USE_RVALUE_REFERENCE + inline value::value(std::string &&s) : type_(string_type), u_() { + u_.string_ = new std::string(std::move(s)); + } + + inline value::value(array &&a) : type_(array_type), u_() { + u_.array_ = new array(std::move(a)); + } + + inline value::value(object &&o) : type_(object_type), u_() { + u_.object_ = new object(std::move(o)); + } +#endif + + inline value::value(const char *s) : type_(string_type), u_() { + u_.string_ = new std::string(s); + } + + inline value::value(const char *s, size_t len) : type_(string_type), u_() { + u_.string_ = new std::string(s, len); + } + + inline void value::clear() { + switch (type_) { +#define DEINIT(p) \ + case p##type: \ + delete u_.p; \ + break + DEINIT(string_); + DEINIT(array_); + DEINIT(object_); +#undef DEINIT + default: + break; + } + } + + inline value::~value() { + clear(); + } + + inline value::value(const value &x) : type_(x.type_), u_() { + switch (type_) { +#define INIT(p, v) \ + case p##type: \ + u_.p = v; \ + break + INIT(string_, new std::string(*x.u_.string_)); + INIT(array_, new array(*x.u_.array_)); + INIT(object_, new object(*x.u_.object_)); +#undef INIT + default: + u_ = x.u_; + break; + } + } + + inline value &value::operator=(const value &x) { + if (this != &x) { + value t(x); + swap(t); + } + return *this; + } + +#if PICOJSON_USE_RVALUE_REFERENCE + inline value::value(value &&x) throw() : type_(null_type), u_() { + swap(x); + } + inline value &value::operator=(value &&x) throw() { + swap(x); + return *this; + } +#endif + inline void value::swap(value &x) throw() { + std::swap(type_, x.type_); + std::swap(u_, x.u_); + } + +#define IS(ctype, jtype) \ + template <> inline bool value::is() const { \ + return type_ == jtype##_type; \ + } + IS(null, null) + IS(bool, boolean) +#ifdef PICOJSON_USE_INT64 + IS(int64_t, int64) +#endif + IS(std::string, string) + IS(array, array) + IS(object, object) +#undef IS + template <> inline bool value::is() const { + return type_ == number_type +#ifdef PICOJSON_USE_INT64 + || type_ == int64_type +#endif + ; + } + +#define GET(ctype, var) \ + template <> inline const ctype &value::get() const { \ + PICOJSON_ASSERT("type mismatch! call is() before get()" && is()); \ + return var; \ + } \ + template <> inline ctype &value::get() { \ + PICOJSON_ASSERT("type mismatch! call is() before get()" && is()); \ + return var; \ + } + GET(bool, u_.boolean_) + GET(std::string, *u_.string_) + GET(array, *u_.array_) + GET(object, *u_.object_) +#ifdef PICOJSON_USE_INT64 + GET(double, + (type_ == int64_type && (const_cast(this)->type_ = number_type, const_cast(this)->u_.number_ = u_.int64_), + u_.number_)) +GET(int64_t, u_.int64_) +#else + GET(double, u_.number_) +#endif +#undef GET + +#define SET(ctype, jtype, setter) \ + template <> inline void value::set(const ctype &_val) { \ + clear(); \ + type_ = jtype##_type; \ + setter \ + } + SET(bool, boolean, u_.boolean_ = _val;) + SET(std::string, string, u_.string_ = new std::string(_val);) + SET(array, array, u_.array_ = new array(_val);) + SET(object, object, u_.object_ = new object(_val);) + SET(double, number, u_.number_ = _val;) +#ifdef PICOJSON_USE_INT64 + SET(int64_t, int64, u_.int64_ = _val;) +#endif +#undef SET + +#if PICOJSON_USE_RVALUE_REFERENCE +#define MOVESET(ctype, jtype, setter) \ + template <> inline void value::set(ctype && _val) { \ + clear(); \ + type_ = jtype##_type; \ + setter \ + } + MOVESET(std::string, string, u_.string_ = new std::string(std::move(_val));) + MOVESET(array, array, u_.array_ = new array(std::move(_val));) + MOVESET(object, object, u_.object_ = new object(std::move(_val));) +#undef MOVESET +#endif + + inline bool value::evaluate_as_boolean() const { + switch (type_) { + case null_type: + return false; + case boolean_type: + return u_.boolean_; + case number_type: + return u_.number_ != 0; +#ifdef PICOJSON_USE_INT64 + case int64_type: + return u_.int64_ != 0; +#endif + case string_type: + return !u_.string_->empty(); + default: + return true; + } + } + + inline const value &value::get(const size_t idx) const { + static value s_null; + PICOJSON_ASSERT(is()); + return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; + } + + inline value &value::get(const size_t idx) { + static value s_null; + PICOJSON_ASSERT(is()); + return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; + } + + inline const value &value::get(const std::string &key) const { + static value s_null; + PICOJSON_ASSERT(is()); + object::const_iterator i = u_.object_->find(key); + return i != u_.object_->end() ? i->second : s_null; + } + + inline value &value::get(const std::string &key) { + static value s_null; + PICOJSON_ASSERT(is()); + object::iterator i = u_.object_->find(key); + return i != u_.object_->end() ? i->second : s_null; + } + + inline bool value::contains(const size_t idx) const { + PICOJSON_ASSERT(is()); + return idx < u_.array_->size(); + } + + inline bool value::contains(const std::string &key) const { + PICOJSON_ASSERT(is()); + object::const_iterator i = u_.object_->find(key); + return i != u_.object_->end(); + } + + inline std::string value::to_str() const { + switch (type_) { + case null_type: + return "null"; + case boolean_type: + return u_.boolean_ ? "true" : "false"; +#ifdef PICOJSON_USE_INT64 + case int64_type: { + char buf[sizeof("-9223372036854775808")]; + SNPRINTF(buf, sizeof(buf), "%" PRId64, u_.int64_); + return buf; + } +#endif + case number_type: { + char buf[256]; + double tmp; + SNPRINTF(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ? "%.f" : "%.17g", u_.number_); +#if PICOJSON_USE_LOCALE + char *decimal_point = localeconv()->decimal_point; + if (strcmp(decimal_point, ".") != 0) { + size_t decimal_point_len = strlen(decimal_point); + for (char *p = buf; *p != '\0'; ++p) { + if (strncmp(p, decimal_point, decimal_point_len) == 0) { + return std::string(buf, p) + "." + (p + decimal_point_len); + } + } + } +#endif + return buf; + } + case string_type: + return *u_.string_; + case array_type: + return "array"; + case object_type: + return "object"; + default: + PICOJSON_ASSERT(0); +#ifdef _MSC_VER + __assume(0); +#endif + } + return std::string(); + } + + template void copy(const std::string &s, Iter oi) { + std::copy(s.begin(), s.end(), oi); + } + + template struct serialize_str_char { + Iter oi; + void operator()(char c) { + switch (c) { +#define MAP(val, sym) \ + case val: \ + copy(sym, oi); \ + break + MAP('"', "\\\""); + MAP('\\', "\\\\"); + MAP('/', "\\/"); + MAP('\b', "\\b"); + MAP('\f', "\\f"); + MAP('\n', "\\n"); + MAP('\r', "\\r"); + MAP('\t', "\\t"); +#undef MAP + default: + if (static_cast(c) < 0x20 || c == 0x7f) { + char buf[7]; + SNPRINTF(buf, sizeof(buf), "\\u%04x", c & 0xff); + copy(buf, buf + 6, oi); + } else { + *oi++ = c; + } + break; + } + } + }; + + template void serialize_str(const std::string &s, Iter oi) { + *oi++ = '"'; + serialize_str_char process_char = {oi}; + std::for_each(s.begin(), s.end(), process_char); + *oi++ = '"'; + } + + template void value::serialize(Iter oi, bool prettify) const { + return _serialize(oi, prettify ? 0 : -1); + } + + inline std::string value::serialize(bool prettify) const { + return _serialize(prettify ? 0 : -1); + } + + template void value::_indent(Iter oi, int indent) { + *oi++ = '\n'; + for (int i = 0; i < indent * INDENT_WIDTH; ++i) { + *oi++ = ' '; + } + } + + template void value::_serialize(Iter oi, int indent) const { + switch (type_) { + case string_type: + serialize_str(*u_.string_, oi); + break; + case array_type: { + *oi++ = '['; + if (indent != -1) { + ++indent; + } + for (array::const_iterator i = u_.array_->begin(); i != u_.array_->end(); ++i) { + if (i != u_.array_->begin()) { + *oi++ = ','; + } + if (indent != -1) { + _indent(oi, indent); + } + i->_serialize(oi, indent); + } + if (indent != -1) { + --indent; + if (!u_.array_->empty()) { + _indent(oi, indent); + } + } + *oi++ = ']'; + break; + } + case object_type: { + *oi++ = '{'; + if (indent != -1) { + ++indent; + } + for (object::const_iterator i = u_.object_->begin(); i != u_.object_->end(); ++i) { + if (i != u_.object_->begin()) { + *oi++ = ','; + } + if (indent != -1) { + _indent(oi, indent); + } + serialize_str(i->first, oi); + *oi++ = ':'; + if (indent != -1) { + *oi++ = ' '; + } + i->second._serialize(oi, indent); + } + if (indent != -1) { + --indent; + if (!u_.object_->empty()) { + _indent(oi, indent); + } + } + *oi++ = '}'; + break; + } + default: + copy(to_str(), oi); + break; + } + if (indent == 0) { + *oi++ = '\n'; + } + } + + inline std::string value::_serialize(int indent) const { + std::string s; + _serialize(std::back_inserter(s), indent); + return s; + } + + template class input { + protected: + Iter cur_, end_; + bool consumed_; + int line_; + + public: + input(const Iter &first, const Iter &last) : cur_(first), end_(last), consumed_(false), line_(1) { + } + int getc() { + if (consumed_) { + if (*cur_ == '\n') { + ++line_; + } + ++cur_; + } + if (cur_ == end_) { + consumed_ = false; + return -1; + } + consumed_ = true; + return *cur_ & 0xff; + } + void ungetc() { + consumed_ = false; + } + Iter cur() const { + if (consumed_) { + input *self = const_cast *>(this); + self->consumed_ = false; + ++self->cur_; + } + return cur_; + } + int line() const { + return line_; + } + void skip_ws() { + while (1) { + int ch = getc(); + if (!(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) { + ungetc(); + break; + } + } + } + bool expect(const int expected) { + skip_ws(); + if (getc() != expected) { + ungetc(); + return false; + } + return true; + } + bool match(const std::string &pattern) { + for (std::string::const_iterator pi(pattern.begin()); pi != pattern.end(); ++pi) { + if (getc() != *pi) { + ungetc(); + return false; + } + } + return true; + } + }; + + template inline int _parse_quadhex(input &in) { + int uni_ch = 0, hex; + for (int i = 0; i < 4; i++) { + if ((hex = in.getc()) == -1) { + return -1; + } + if ('0' <= hex && hex <= '9') { + hex -= '0'; + } else if ('A' <= hex && hex <= 'F') { + hex -= 'A' - 0xa; + } else if ('a' <= hex && hex <= 'f') { + hex -= 'a' - 0xa; + } else { + in.ungetc(); + return -1; + } + uni_ch = uni_ch * 16 + hex; + } + return uni_ch; + } + + template inline bool _parse_codepoint(String &out, input &in) { + int uni_ch; + if ((uni_ch = _parse_quadhex(in)) == -1) { + return false; + } + if (0xd800 <= uni_ch && uni_ch <= 0xdfff) { + if (0xdc00 <= uni_ch) { + // a second 16-bit of a surrogate pair appeared + return false; + } + // first 16-bit of surrogate pair, get the next one + if (in.getc() != '\\' || in.getc() != 'u') { + in.ungetc(); + return false; + } + int second = _parse_quadhex(in); + if (!(0xdc00 <= second && second <= 0xdfff)) { + return false; + } + uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff); + uni_ch += 0x10000; + } + if (uni_ch < 0x80) { + out.push_back(static_cast(uni_ch)); + } else { + if (uni_ch < 0x800) { + out.push_back(static_cast(0xc0 | (uni_ch >> 6))); + } else { + if (uni_ch < 0x10000) { + out.push_back(static_cast(0xe0 | (uni_ch >> 12))); + } else { + out.push_back(static_cast(0xf0 | (uni_ch >> 18))); + out.push_back(static_cast(0x80 | ((uni_ch >> 12) & 0x3f))); + } + out.push_back(static_cast(0x80 | ((uni_ch >> 6) & 0x3f))); + } + out.push_back(static_cast(0x80 | (uni_ch & 0x3f))); + } + return true; + } + + template inline bool _parse_string(String &out, input &in) { + while (1) { + int ch = in.getc(); + if (ch < ' ') { + in.ungetc(); + return false; + } else if (ch == '"') { + return true; + } else if (ch == '\\') { + if ((ch = in.getc()) == -1) { + return false; + } + switch (ch) { +#define MAP(sym, val) \ + case sym: \ + out.push_back(val); \ + break + MAP('"', '\"'); + MAP('\\', '\\'); + MAP('/', '/'); + MAP('b', '\b'); + MAP('f', '\f'); + MAP('n', '\n'); + MAP('r', '\r'); + MAP('t', '\t'); +#undef MAP + case 'u': + if (!_parse_codepoint(out, in)) { + return false; + } + break; + default: + return false; + } + } else { + out.push_back(static_cast(ch)); + } + } + return false; + } + + template inline bool _parse_array(Context &ctx, input &in) { + if (!ctx.parse_array_start()) { + return false; + } + size_t idx = 0; + if (in.expect(']')) { + return ctx.parse_array_stop(idx); + } + do { + if (!ctx.parse_array_item(in, idx)) { + return false; + } + idx++; + } while (in.expect(',')); + return in.expect(']') && ctx.parse_array_stop(idx); + } + + template inline bool _parse_object(Context &ctx, input &in) { + if (!ctx.parse_object_start()) { + return false; + } + if (in.expect('}')) { + return true; + } + do { + std::string key; + if (!in.expect('"') || !_parse_string(key, in) || !in.expect(':')) { + return false; + } + if (!ctx.parse_object_item(in, key)) { + return false; + } + } while (in.expect(',')); + return in.expect('}'); + } + + template inline std::string _parse_number(input &in) { + std::string num_str; + while (1) { + int ch = in.getc(); + if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == 'e' || ch == 'E') { + num_str.push_back(static_cast(ch)); + } else if (ch == '.') { +#if PICOJSON_USE_LOCALE + num_str += localeconv()->decimal_point; +#else + num_str.push_back('.'); +#endif + } else { + in.ungetc(); + break; + } + } + return num_str; + } + + template inline bool _parse(Context &ctx, input &in) { + in.skip_ws(); + int ch = in.getc(); + switch (ch) { +#define IS(ch, text, op) \ + case ch: \ + if (in.match(text) && op) { \ + return true; \ + } else { \ + return false; \ + } + IS('n', "ull", ctx.set_null()); + IS('f', "alse", ctx.set_bool(false)); + IS('t', "rue", ctx.set_bool(true)); +#undef IS + case '"': + return ctx.parse_string(in); + case '[': + return _parse_array(ctx, in); + case '{': + return _parse_object(ctx, in); + default: + if (('0' <= ch && ch <= '9') || ch == '-') { + double f; + char *endp; + in.ungetc(); + std::string num_str(_parse_number(in)); + if (num_str.empty()) { + return false; + } +#ifdef PICOJSON_USE_INT64 + { + errno = 0; + intmax_t ival = strtoimax(num_str.c_str(), &endp, 10); + if (errno == 0 && std::numeric_limits::min() <= ival && ival <= std::numeric_limits::max() && + endp == num_str.c_str() + num_str.size()) { + ctx.set_int64(ival); + return true; + } + } +#endif + f = strtod(num_str.c_str(), &endp); + if (endp == num_str.c_str() + num_str.size()) { + ctx.set_number(f); + return true; + } + return false; + } + break; + } + in.ungetc(); + return false; + } + + class deny_parse_context { + public: + bool set_null() { + return false; + } + bool set_bool(bool) { + return false; + } +#ifdef PICOJSON_USE_INT64 + bool set_int64(int64_t) { + return false; + } +#endif + bool set_number(double) { + return false; + } + template bool parse_string(input &) { + return false; + } + bool parse_array_start() { + return false; + } + template bool parse_array_item(input &, size_t) { + return false; + } + bool parse_array_stop(size_t) { + return false; + } + bool parse_object_start() { + return false; + } + template bool parse_object_item(input &, const std::string &) { + return false; + } + }; + + class default_parse_context { + protected: + value *out_; + + public: + default_parse_context(value *out) : out_(out) { + } + bool set_null() { + *out_ = value(); + return true; + } + bool set_bool(bool b) { + *out_ = value(b); + return true; + } +#ifdef PICOJSON_USE_INT64 + bool set_int64(int64_t i) { + *out_ = value(i); + return true; + } +#endif + bool set_number(double f) { + *out_ = value(f); + return true; + } + template bool parse_string(input &in) { + *out_ = value(string_type, false); + return _parse_string(out_->get(), in); + } + bool parse_array_start() { + *out_ = value(array_type, false); + return true; + } + template bool parse_array_item(input &in, size_t) { + array &a = out_->get(); + a.push_back(value()); + default_parse_context ctx(&a.back()); + return _parse(ctx, in); + } + bool parse_array_stop(size_t) { + return true; + } + bool parse_object_start() { + *out_ = value(object_type, false); + return true; + } + template bool parse_object_item(input &in, const std::string &key) { + object &o = out_->get(); + default_parse_context ctx(&o[key]); + return _parse(ctx, in); + } + + private: + default_parse_context(const default_parse_context &); + default_parse_context &operator=(const default_parse_context &); + }; + + class null_parse_context { + public: + struct dummy_str { + void push_back(int) { + } + }; + + public: + null_parse_context() { + } + bool set_null() { + return true; + } + bool set_bool(bool) { + return true; + } +#ifdef PICOJSON_USE_INT64 + bool set_int64(int64_t) { + return true; + } +#endif + bool set_number(double) { + return true; + } + template bool parse_string(input &in) { + dummy_str s; + return _parse_string(s, in); + } + bool parse_array_start() { + return true; + } + template bool parse_array_item(input &in, size_t) { + return _parse(*this, in); + } + bool parse_array_stop(size_t) { + return true; + } + bool parse_object_start() { + return true; + } + template bool parse_object_item(input &in, const std::string &) { + return _parse(*this, in); + } + + private: + null_parse_context(const null_parse_context &); + null_parse_context &operator=(const null_parse_context &); + }; + +// obsolete, use the version below + template inline std::string parse(value &out, Iter &pos, const Iter &last) { + std::string err; + pos = parse(out, pos, last, &err); + return err; + } + + template inline Iter _parse(Context &ctx, const Iter &first, const Iter &last, std::string *err) { + input in(first, last); + if (!_parse(ctx, in) && err != NULL) { + char buf[64]; + SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line()); + *err = buf; + while (1) { + int ch = in.getc(); + if (ch == -1 || ch == '\n') { + break; + } else if (ch >= ' ') { + err->push_back(static_cast(ch)); + } + } + } + return in.cur(); + } + + template inline Iter parse(value &out, const Iter &first, const Iter &last, std::string *err) { + default_parse_context ctx(&out); + return _parse(ctx, first, last, err); + } + + inline std::string parse(value &out, const std::string &s) { + std::string err; + parse(out, s.begin(), s.end(), &err); + return err; + } + + inline std::string parse(value &out, std::istream &is) { + std::string err; + parse(out, std::istreambuf_iterator(is.rdbuf()), std::istreambuf_iterator(), &err); + return err; + } + + template struct last_error_t { static std::string s; }; + template std::string last_error_t::s; + + inline void set_last_error(const std::string &s) { + last_error_t::s = s; + } + + inline const std::string &get_last_error() { + return last_error_t::s; + } + + inline bool operator==(const value &x, const value &y) { + if (x.is()) + return y.is(); +#define PICOJSON_CMP(type) \ + if (x.is()) \ + return y.is() && x.get() == y.get() + PICOJSON_CMP(bool); + PICOJSON_CMP(double); + PICOJSON_CMP(std::string); + PICOJSON_CMP(array); + PICOJSON_CMP(object); +#undef PICOJSON_CMP + PICOJSON_ASSERT(0); +#ifdef _MSC_VER + __assume(0); +#endif + return false; + } + + inline bool operator!=(const value &x, const value &y) { + return !(x == y); + } +} + +#if !PICOJSON_USE_RVALUE_REFERENCE +namespace std { +template <> inline void swap(picojson::value &x, picojson::value &y) { + x.swap(y); +} +} +#endif + +inline std::istream &operator>>(std::istream &is, picojson::value &x) { + picojson::set_last_error(std::string()); + const std::string err(picojson::parse(x, is)); + if (!err.empty()) { + picojson::set_last_error(err); + is.setstate(std::ios::failbit); + } + return is; +} + +inline std::ostream &operator<<(std::ostream &os, const picojson::value &x) { + x.serialize(std::ostream_iterator(os)); + return os; +} +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif \ No newline at end of file From 72d63f5fe71fff9249e63cd52bb649d3741d12c1 Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Sun, 18 Mar 2018 09:09:56 +0100 Subject: [PATCH 03/16] Update picojson.h to commit fddad5f573b9247da81a54632cafab39b3fd9cff --- include/picojson.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/include/picojson.h b/include/picojson.h index c4590dee..ba4b039b 100644 --- a/include/picojson.h +++ b/include/picojson.h @@ -65,6 +65,14 @@ extern "C" { #endif #endif // PICOJSON_USE_RVALUE_REFERENCE +#ifndef PICOJSON_NOEXCEPT +#if PICOJSON_USE_RVALUE_REFERENCE +#define PICOJSON_NOEXCEPT noexcept +#else +#define PICOJSON_NOEXCEPT throw() +#endif +#endif + // experimental support for int64_t (see README.mkdn for detail) #ifdef PICOJSON_USE_INT64 #define __STDC_FORMAT_MACROS @@ -160,10 +168,10 @@ namespace picojson { value(const value &x); value &operator=(const value &x); #if PICOJSON_USE_RVALUE_REFERENCE - value(value &&x) throw(); - value &operator=(value &&x) throw(); + value(value &&x) PICOJSON_NOEXCEPT; + value &operator=(value &&x) PICOJSON_NOEXCEPT; #endif - void swap(value &x) throw(); + void swap(value &x) PICOJSON_NOEXCEPT; template bool is() const; template const T &get() const; template T &get(); @@ -320,15 +328,15 @@ std::isnan(n) || std::isinf(n) } #if PICOJSON_USE_RVALUE_REFERENCE - inline value::value(value &&x) throw() : type_(null_type), u_() { + inline value::value(value &&x) PICOJSON_NOEXCEPT : type_(null_type), u_() { swap(x); } - inline value &value::operator=(value &&x) throw() { + inline value &value::operator=(value &&x) PICOJSON_NOEXCEPT { swap(x); return *this; } #endif - inline void value::swap(value &x) throw() { + inline void value::swap(value &x) PICOJSON_NOEXCEPT { std::swap(type_, x.type_); std::swap(u_, x.u_); } From 62b88f879589887b6b3883fb55accdf9ef89fcf9 Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Sun, 18 Mar 2018 09:10:43 +0100 Subject: [PATCH 04/16] Version tick to 1.0.7 --- include/sre/Renderer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sre/Renderer.hpp b/include/sre/Renderer.hpp index 4d9b4e98..e73126b4 100755 --- a/include/sre/Renderer.hpp +++ b/include/sre/Renderer.hpp @@ -71,7 +71,7 @@ namespace sre { ~Renderer(); static constexpr int sre_version_major = 1; static constexpr int sre_version_minor = 0; - static constexpr int sre_version_point = 6; + static constexpr int sre_version_point = 7; glm::ivec2 getWindowSize(); // Return the current size of the window From 4b7d6183d52696d203316a5dada944fc90d2764c Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Sun, 18 Mar 2018 11:10:35 +0100 Subject: [PATCH 05/16] Introduce uniform set --- include/sre/Material.hpp | 55 ++++++-------- include/sre/Shader.hpp | 2 +- include/sre/Texture.hpp | 1 + include/sre/impl/UniformSet.hpp | 69 ++++++++++++++++++ src/CMakeLists.txt | 1 + src/sre/Inspector.cpp | 2 +- src/sre/Material.cpp | 124 +++++++------------------------- src/sre/Shader.cpp | 2 +- src/sre/impl/UniformSet.cpp | 72 +++++++++++++++++++ 9 files changed, 194 insertions(+), 134 deletions(-) create mode 100644 include/sre/impl/UniformSet.hpp create mode 100644 src/sre/impl/UniformSet.cpp diff --git a/include/sre/Material.hpp b/include/sre/Material.hpp index f23b5887..83fb07f0 100755 --- a/include/sre/Material.hpp +++ b/include/sre/Material.hpp @@ -11,6 +11,7 @@ #include "sre/Texture.hpp" #include "glm/glm.hpp" #include "sre/Color.hpp" +#include "sre/impl/UniformSet.hpp" #include #include @@ -78,7 +79,7 @@ namespace sre { bool set(std::string uniformName, glm::vec4 value); bool set(std::string uniformName, float value); - bool set(std::string uniformName, std::shared_ptr value); + bool set(std::string uniformName, std::shared_ptr value); bool set(std::string uniformName, std::shared_ptr> value); bool set(std::string uniformName, std::shared_ptr> value); bool set(std::string uniformName, Color value); @@ -92,17 +93,7 @@ namespace sre { std::string name; std::shared_ptr shader; - template - struct DllExport Uniform { - int id; - T value; - }; - - std::vector>> textureValues; - std::vector> vectorValues; - std::vector>>> mat4Values; - std::vector>>> mat3Values; - std::vector> floatValues; + UniformSet uniformMap; friend class Shader; friend class RenderPass; @@ -110,13 +101,14 @@ namespace sre { template<> inline std::shared_ptr Material::get(std::string uniformName) { - auto t = shader->getUniformType(uniformName.c_str()); + auto t = shader->getUniform(uniformName); if (t.type != UniformType::Texture && t.type != UniformType::TextureCube){ return nullptr; } - for (auto & tv : textureValues){ - if (tv.id == t.id){ - return tv.value; + for (auto & tv : uniformMap.textureValues){ + auto res = uniformMap.textureValues.find(t.id); + if (res != uniformMap.textureValues.end()){ + return res->second; } } return nullptr; @@ -124,12 +116,11 @@ namespace sre { template<> inline glm::vec4 Material::get(std::string uniformName) { - auto t = shader->getUniformType(uniformName.c_str()); + auto t = shader->getUniform(uniformName); if (t.type == UniformType::Vec4){ - for (auto & tv : vectorValues){ - if (tv.id == t.id){ - return tv.value; - } + auto res = uniformMap.vectorValues.find(t.id); + if (res != uniformMap.vectorValues.end()){ + return res->second; } } return glm::vec4(0,0,0,0); @@ -137,14 +128,13 @@ namespace sre { template<> inline Color Material::get(std::string uniformName) { - auto t = shader->getUniformType(uniformName.c_str()); + auto t = shader->getUniform(uniformName); if (t.type == UniformType::Vec4){ - for (auto & tv : vectorValues){ - if (tv.id == t.id){ - Color value; - value.setFromLinear(tv.value); - return value; - } + auto res = uniformMap.vectorValues.find(t.id); + if (res != uniformMap.vectorValues.end()){ + Color value; + value.setFromLinear(res->second); + return value; } } return {0,0,0,0}; @@ -152,12 +142,11 @@ namespace sre { template<> inline float Material::get(std::string uniformName) { - auto t = shader->getUniformType(uniformName.c_str()); + auto t = shader->getUniform(uniformName); if (t.type == UniformType::Float) { - for (auto &tv : floatValues) { - if (tv.id == t.id) { - return tv.value; - } + auto res = uniformMap.floatValues.find(t.id); + if (res != uniformMap.floatValues.end()){ + return res->second; } } return 0.0f; diff --git a/include/sre/Shader.hpp b/include/sre/Shader.hpp index ae47d4d0..041ea662 100755 --- a/include/sre/Shader.hpp +++ b/include/sre/Shader.hpp @@ -224,7 +224,7 @@ namespace sre { std::shared_ptr createMaterial(std::map specializationConstants = {}); - Uniform getUniformType(const std::string &name); + Uniform getUniform(const std::string &name); std::pair getAttibuteType(const std::string & name); // Return type, size of the attribute diff --git a/include/sre/Texture.hpp b/include/sre/Texture.hpp index dc7ff7ca..f8281599 100755 --- a/include/sre/Texture.hpp +++ b/include/sre/Texture.hpp @@ -162,6 +162,7 @@ class DllExport Texture : public std::enable_shared_from_this { friend class Inspector; friend class VR; friend class Sprite; + friend class UniformSet; }; diff --git a/include/sre/impl/UniformSet.hpp b/include/sre/impl/UniformSet.hpp new file mode 100644 index 00000000..3c6a94e9 --- /dev/null +++ b/include/sre/impl/UniformSet.hpp @@ -0,0 +1,69 @@ +/* + * SimpleRenderEngine (https://github.com/mortennobel/SimpleRenderEngine) + * + * Created by Morten Nobel-Jørgensen ( http://www.nobel-joergensen.com/ ) + * License: MIT + */ + +#pragma once + +#include "sre/Texture.hpp" +#include "sre/Color.hpp" +#include "glm/glm.hpp" +#include +#include + +namespace sre { + class UniformSet { + public: + void set(int id, glm::vec4 value); + + void set(int id, float value); + + void set(int id, std::shared_ptr value); + + void set(int id, std::shared_ptr> value); + + void set(int id, std::shared_ptr> value); + + void set(int id, Color value); + + void clear(); + + void bind(); + + template + inline T get(int id); + + private: + std::map> textureValues; + std::map vectorValues; + std::map>> mat4Values; + std::map>> mat3Values; + std::map floatValues; + + friend class Material; + }; + + template<> + inline std::shared_ptr UniformSet::get(int id) { + return textureValues[id]; + } + + template<> + inline glm::vec4 UniformSet::get(int id) { + return vectorValues[id]; + } + + template<> + inline Color UniformSet::get(int id) { + Color value; + value.setFromLinear(vectorValues[id]); + return value; + } + + template<> + inline float UniformSet::get(int id) { + return floatValues[id]; + } +} \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ac1e71da..32fd928c 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,6 @@ file(GLOB SOURCE_FILES "sre/*.cpp" + "sre/impl/*.cpp" "../include/sre/*.hpp" "../include/sre/impl/*.hpp" "imgui/*.cpp" diff --git a/src/sre/Inspector.cpp b/src/sre/Inspector.cpp index 19ece1be..a62eb481 100644 --- a/src/sre/Inspector.cpp +++ b/src/sre/Inspector.cpp @@ -294,7 +294,7 @@ namespace sre { if (ImGui::TreeNode("Uniforms")) { auto uniformNames = shader->getUniformNames(); for (auto a : uniformNames){ - auto type = shader->getUniformType(a); + auto type = shader->getUniform(a); std::string typeStr = glUniformToString(type.type); typeStr = appendSize(typeStr, type.arraySize); ImGui::LabelText(a.c_str(), typeStr.c_str()); diff --git a/src/sre/Material.cpp b/src/sre/Material.cpp index 1d48eb18..fae8412a 100755 --- a/src/sre/Material.cpp +++ b/src/sre/Material.cpp @@ -26,29 +26,7 @@ namespace sre { } void Material::bind(){ - unsigned int textureSlot = 0; - for (const auto & t : textureValues) { - glActiveTexture(GL_TEXTURE0 + textureSlot); - glBindTexture(t.value->target, t.value->textureId); - glUniform1i(t.id, textureSlot); - textureSlot++; - } - for (auto& t : vectorValues) { - glUniform4fv(t.id, 1, glm::value_ptr(t.value)); - } - for (auto& t : floatValues) { - glUniform1f(t.id, t.value); - } - for (auto& t : mat3Values) { - if (t.value.get()) { - glUniformMatrix3fv(t.id, static_cast(t.value->size()), GL_FALSE, glm::value_ptr((*t.value)[0])); - } - } - for (auto& t : mat4Values) { - if (t.value.get()){ - glUniformMatrix4fv(t.id, static_cast(t.value->size()), GL_FALSE, glm::value_ptr((*t.value)[0])); - } - } + uniformMap.bind(); } std::shared_ptr Material::getShader() { @@ -58,56 +36,38 @@ namespace sre { void Material::setShader(std::shared_ptr shader) { Material::shader = shader; - textureValues.clear(); - vectorValues.clear(); - floatValues.clear(); + uniformMap.clear(); for (auto & u : shader->uniforms){ switch (u.type){ case UniformType::Vec4: { - Uniform uniform; - uniform.id = u.id; - uniform.value = glm::vec4(1.0f,1.0f,1.0f,1.0f); - vectorValues.push_back(uniform); + uniformMap.set(u.id, glm::vec4(1.0f,1.0f,1.0f,1.0f)); } break; case UniformType::Texture: { - Uniform> uniform; - uniform.id = u.id; - uniform.value = Texture::getWhiteTexture(); - textureValues.push_back(uniform); + uniformMap.set(u.id, Texture::getWhiteTexture()); } break; case UniformType::TextureCube: { - Uniform> uniform; - uniform.id = u.id; - uniform.value = Texture::getDefaultCubemapTexture(); - textureValues.push_back(uniform); + uniformMap.set(u.id, Texture::getDefaultCubemapTexture()); } break; case UniformType::Float: { - Uniform uniform; - uniform.id = u.id; - uniform.value = 0.0f; - floatValues.push_back(uniform); + uniformMap.set(u.id, 0.0f); } break; case UniformType::Mat3: { - Uniform>> uniform; - uniform.id = u.id; - mat3Values.push_back(uniform); + uniformMap.set(u.id, std::shared_ptr>()); } break; case UniformType::Mat4: { - Uniform>> uniform; - uniform.id = u.id; - mat4Values.push_back(uniform); + uniformMap.set(u.id, std::shared_ptr>()); } break; default: @@ -150,71 +110,39 @@ namespace sre { } bool Material::set(std::string uniformName, glm::vec4 value){ - auto type = shader->getUniformType(uniformName); - for (auto & v : vectorValues){ - if (v.id==type.id){ - v.value = value; - return true; - } - } - return false; + auto type = shader->getUniform(uniformName); + uniformMap.set(type.id, value); + return true; } bool Material::set(std::string uniformName, std::shared_ptr> value){ - auto type = shader->getUniformType(uniformName); - for (auto & v : mat3Values){ - if (v.id==type.id){ - v.value = value; - return true; - } - } - return false; + auto type = shader->getUniform(uniformName); + uniformMap.set(type.id, value); + return true; } bool Material::set(std::string uniformName, std::shared_ptr> value){ - auto type = shader->getUniformType(uniformName); - for (auto & v : mat4Values){ - if (v.id==type.id){ - v.value = value; - return true; - } - } - return false; + auto type = shader->getUniform(uniformName); + uniformMap.set(type.id, value); + return true; } bool Material::set(std::string uniformName, Color value){ - auto type = shader->getUniformType(uniformName); - for (auto & v : vectorValues){ - if (v.id==type.id){ - v.value = value.toLinear(); - return true; - } - } - return false; + auto type = shader->getUniform(uniformName); + uniformMap.set(type.id, value); + return true; } - - bool Material::set(std::string uniformName, float value){ - auto type = shader->getUniformType(uniformName); - for (auto & v : floatValues){ - if (v.id==type.id){ - v.value = value; - return true; - } - } - return false; + auto type = shader->getUniform(uniformName); + uniformMap.set(type.id, value); + return true; } bool Material::set(std::string uniformName, std::shared_ptr value){ - auto type = shader->getUniformType(uniformName); - for (auto & v : textureValues){ - if (v.id==type.id){ - v.value = value; - return true; - } - } - return false; + auto type = shader->getUniform(uniformName); + uniformMap.set(type.id, value); + return true; } std::shared_ptr Material::getMetallicRoughnessTexture() { diff --git a/src/sre/Shader.cpp b/src/sre/Shader.cpp index 3650ed40..3edf3558 100755 --- a/src/sre/Shader.cpp +++ b/src/sre/Shader.cpp @@ -685,7 +685,7 @@ namespace sre { return standardPBR; } - Uniform Shader::getUniformType(const std::string &name) { + Uniform Shader::getUniform(const std::string &name) { for (auto i = uniforms.cbegin(); i != uniforms.cend(); i++) { if (i->name.compare(name) == 0) return *i; diff --git a/src/sre/impl/UniformSet.cpp b/src/sre/impl/UniformSet.cpp new file mode 100644 index 00000000..c12cf94b --- /dev/null +++ b/src/sre/impl/UniformSet.cpp @@ -0,0 +1,72 @@ +/* + * SimpleRenderEngine (https://github.com/mortennobel/SimpleRenderEngine) + * + * Created by Morten Nobel-Jørgensen ( http://www.nobel-joergensen.com/ ) + * License: MIT + */ +#include +#include "sre/impl/UniformSet.hpp" + +namespace sre { + + void UniformSet::bind(){ + unsigned int textureSlot = 0; + for (const auto & t : textureValues) { + + glActiveTexture(GL_TEXTURE0 + textureSlot); + glBindTexture(t.second->target, t.second->textureId); + glUniform1i(t.first, textureSlot); + textureSlot++; + } + for (auto& t : vectorValues) { + glUniform4fv(t.first, 1, glm::value_ptr(t.second)); + } + for (auto& t : floatValues) { + glUniform1f(t.first, t.second); + } + for (auto& t : mat3Values) { + if (t.second.get()) { + glm::mat3& m3 = (*t.second)[0]; + glUniformMatrix3fv(t.first, static_cast(t.second->size()), GL_FALSE, glm::value_ptr(m3)); + } + } + for (auto& t : mat4Values) { + if (t.second.get()){ + glm::mat4& m4 = (*t.second)[0]; + glUniformMatrix4fv(t.first, static_cast(t.second->size()), GL_FALSE, glm::value_ptr(m4)); + } + } + } + + void UniformSet::set(int id, glm::vec4 value){ + vectorValues[id] = value; + } + + void UniformSet::set(int id, float value){ + floatValues[id] = value; + } + + void UniformSet::set(int id, std::shared_ptr value){ + textureValues[id] = value; + } + + void UniformSet::set(int id, std::shared_ptr> value){ + mat3Values[id] = value; + } + + void UniformSet::set(int id, std::shared_ptr> value){ + mat4Values[id] = value; + } + + void UniformSet::set(int id, Color value){ + vectorValues[id] = value.toLinear();; + } + + void UniformSet::clear(){ + textureValues.clear(); + vectorValues.clear(); + mat4Values.clear(); + mat3Values.clear(); + floatValues.clear(); + } +} \ No newline at end of file From 6369c696d42e95cbd2feb3b9b778d88f75fe50de Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Sun, 18 Mar 2018 11:53:20 +0100 Subject: [PATCH 06/16] Performance improvements (reducing uniform changes) --- include/sre/RenderPass.hpp | 2 + src/sre/RenderPass.cpp | 85 ++++++++++++++++++++------------------ 2 files changed, 46 insertions(+), 41 deletions(-) diff --git a/include/sre/RenderPass.hpp b/include/sre/RenderPass.hpp index a2e4120b..02223c4a 100755 --- a/include/sre/RenderPass.hpp +++ b/include/sre/RenderPass.hpp @@ -133,6 +133,7 @@ namespace sre { RenderPass::RenderPassBuilder builder; explicit RenderPass(RenderPass::RenderPassBuilder& builder); + void setupShaderRenderPass(Shader *shader); void setupShader(const glm::mat4 &modelTransform, Shader *shader); Shader* lastBoundShader = nullptr; @@ -142,6 +143,7 @@ namespace sre { glm::mat4 projection; glm::uvec2 viewportOffset; glm::uvec2 viewportSize; + std::set shaders; friend class Renderer; }; diff --git a/src/sre/RenderPass.cpp b/src/sre/RenderPass.cpp index a7313ce6..69bad221 100755 --- a/src/sre/RenderPass.cpp +++ b/src/sre/RenderPass.cpp @@ -130,49 +130,41 @@ namespace sre { renderQueue.emplace_back(RenderQueueObj{meshPtr, modelTransform, {material_ptr}}); } + void RenderPass::setupShaderRenderPass(Shader *shader){ + if (shader->uniformLocationView != -1) { + glUniformMatrix4fv(shader->uniformLocationView, 1, GL_FALSE, glm::value_ptr(builder.camera.viewTransform)); + } + if (shader->uniformLocationProjection != -1) { + glUniformMatrix4fv(shader->uniformLocationProjection, 1, GL_FALSE, glm::value_ptr(projection)); + } + + if (shader->uniformLocationViewport != -1) { + glm::vec4 viewport((float)viewportSize.x,(float)viewportSize.y,(float)viewportOffset.x,(float)viewportOffset.y); + glUniform4fv(shader->uniformLocationViewport, 1, glm::value_ptr(viewport)); + } + if (shader->uniformLocationCameraPosition != -1) { + glm::vec4 cameraPos = glm::vec4(this->builder.camera.getPosition(),1.0f); + glUniform4fv(shader->uniformLocationCameraPosition, 1, glm::value_ptr(cameraPos)); + } + shader->setLights(builder.worldLights); + } + void RenderPass::setupShader(const glm::mat4 &modelTransform, Shader *shader) { - if (lastBoundShader == shader){ - if (shader->uniformLocationModel != -1){ - glUniformMatrix4fv(shader->uniformLocationModel, 1, GL_FALSE, glm::value_ptr(modelTransform)); - } - if (shader->uniformLocationModelViewInverseTranspose != -1){ - auto normalMatrix = transpose(inverse(((glm::mat3)builder.camera.getViewTransform()) * ((glm::mat3)modelTransform))); - glUniformMatrix3fv(shader->uniformLocationModelViewInverseTranspose, 1, GL_FALSE, glm::value_ptr(normalMatrix)); - } - if (shader->uniformLocationModelInverseTranspose != -1){ - auto normalMatrix = transpose(inverse((glm::mat3)modelTransform)); - glUniformMatrix3fv(shader->uniformLocationModelInverseTranspose, 1, GL_FALSE, glm::value_ptr(normalMatrix)); - } - } else { + if (lastBoundShader != shader){ builder.renderStats->stateChangesShader++; lastBoundShader = shader; shader->bind(); - if (shader->uniformLocationModel != -1) { - glUniformMatrix4fv(shader->uniformLocationModel, 1, GL_FALSE, glm::value_ptr(modelTransform)); - } - if (shader->uniformLocationView != -1) { - glUniformMatrix4fv(shader->uniformLocationView, 1, GL_FALSE, glm::value_ptr(builder.camera.viewTransform)); - } - if (shader->uniformLocationProjection != -1) { - glUniformMatrix4fv(shader->uniformLocationProjection, 1, GL_FALSE, glm::value_ptr(projection)); - } - if (shader->uniformLocationModelViewInverseTranspose != -1) { - auto normalMatrix = transpose(inverse(((glm::mat3)builder.camera.getViewTransform()) * ((glm::mat3)modelTransform))); - glUniformMatrix3fv(shader->uniformLocationModelViewInverseTranspose, 1, GL_FALSE, glm::value_ptr(normalMatrix)); - } - if (shader->uniformLocationModelInverseTranspose != -1) { - auto normalMatrix = transpose(inverse((glm::mat3)modelTransform)); - glUniformMatrix3fv(shader->uniformLocationModelInverseTranspose, 1, GL_FALSE, glm::value_ptr(normalMatrix)); - } - if (shader->uniformLocationViewport != -1) { - glm::vec4 viewport((float)viewportSize.x,(float)viewportSize.y,(float)viewportOffset.x,(float)viewportOffset.y); - glUniform4fv(shader->uniformLocationViewport, 1, glm::value_ptr(viewport)); - } - if (shader->uniformLocationCameraPosition != -1) { - glm::vec4 cameraPos = glm::vec4(this->builder.camera.getPosition(),1.0f); - glUniform4fv(shader->uniformLocationCameraPosition, 1, glm::value_ptr(cameraPos)); - } - shader->setLights(builder.worldLights); + } + if (shader->uniformLocationModel != -1){ + glUniformMatrix4fv(shader->uniformLocationModel, 1, GL_FALSE, glm::value_ptr(modelTransform)); + } + if (shader->uniformLocationModelViewInverseTranspose != -1){ + auto normalMatrix = transpose(inverse(((glm::mat3)builder.camera.getViewTransform()) * ((glm::mat3)modelTransform))); + glUniformMatrix3fv(shader->uniformLocationModelViewInverseTranspose, 1, GL_FALSE, glm::value_ptr(normalMatrix)); + } + if (shader->uniformLocationModelInverseTranspose != -1){ + auto normalMatrix = transpose(inverse((glm::mat3)modelTransform)); + glUniformMatrix3fv(shader->uniformLocationModelInverseTranspose, 1, GL_FALSE, glm::value_ptr(normalMatrix)); } } @@ -236,10 +228,21 @@ namespace sre { glClear(clear); } - - projection = builder.camera.getProjectionTransform(viewportSize); + // find list of used shaders + shaders.clear(); + for (auto & rqObj : renderQueue){ + for (auto & mat : rqObj.materials){ + shaders.insert(mat->getShader().get()); + } + } + // update global uniforms + for (auto shader : shaders){ + glUseProgram(shader->shaderProgramId); + setupShaderRenderPass(shader); + } + for (auto & rqObj : renderQueue){ drawInstance(rqObj); } From 236b60337e867dd74a51739a7722d2e76252595d Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Sun, 18 Mar 2018 14:49:14 +0100 Subject: [PATCH 07/16] Introduce global_uniforms_incl.glsl --- glsl-style.md | 2 +- include/sre/WorldLights.hpp | 2 +- include/sre/impl/ShaderSource.inl | 80 +++++++++++-------- src/embedded_deps/blit_vert.glsl | 3 +- src/embedded_deps/debug_normal_vert.glsl | 3 +- src/embedded_deps/debug_tangent_vert.glsl | 3 +- src/embedded_deps/debug_uv_vert.glsl | 3 +- src/embedded_deps/global_uniforms_incl.glsl | 24 ++++++ src/embedded_deps/light_incl.glsl | 4 +- src/embedded_deps/particles_frag.glsl | 7 +- src/embedded_deps/particles_vert.glsl | 4 +- src/embedded_deps/sprite_vert.glsl | 3 +- .../standard_blinn_phong_frag.glsl | 2 +- .../standard_blinn_phong_vert.glsl | 3 +- src/embedded_deps/standard_pbr_frag.glsl | 5 +- src/embedded_deps/standard_pbr_vert.glsl | 3 +- src/embedded_deps/standard_phong_frag.glsl | 3 +- src/embedded_deps/standard_phong_vert.glsl | 5 +- src/embedded_deps/unlit_vert.glsl | 3 +- src/sre/Shader.cpp | 7 +- src/sre/WorldLights.cpp | 4 +- 21 files changed, 98 insertions(+), 75 deletions(-) create mode 100644 src/embedded_deps/global_uniforms_incl.glsl diff --git a/glsl-style.md b/glsl-style.md index ce850483..2ad99adf 100644 --- a/glsl-style.md +++ b/glsl-style.md @@ -20,7 +20,7 @@ Simple Render Engine provides some coding styles: **Light** -* glm::vec3 **g_ambientLight**. Automatically set from WorldLight::ambientLight +* glm::vec4 **g_ambientLight**. Automatically set from WorldLight::ambientLight (w is ignored) * glm::vec4[] **g_lightPosType**. Contains a number of scene light positions (.xyz) and types (.w). (w==0 is directional light, w==1 is point light) * glm::vec4[] **g_lightColorRange**. Contains a number of scene light colors (.xyz) and range (.w). diff --git a/include/sre/WorldLights.hpp b/include/sre/WorldLights.hpp index a8e0b678..3c1afa69 100755 --- a/include/sre/WorldLights.hpp +++ b/include/sre/WorldLights.hpp @@ -24,7 +24,7 @@ namespace sre { void setAmbientLight(const glm::vec3& light); // Set ambient light glm::vec3 getAmbientLight(); // Get ambient light private: - glm::vec3 ambientLight; + glm::vec4 ambientLight; std::vector lights; friend class Shader; diff --git a/include/sre/impl/ShaderSource.inl b/include/sre/impl/ShaderSource.inl index 74ca4162..ac9bd6e4 100644 --- a/include/sre/impl/ShaderSource.inl +++ b/include/sre/impl/ShaderSource.inl @@ -1,5 +1,5 @@ // autogenerated by -// files_to_cpp shader src/embedded_deps/sre_utils_incl.glsl sre_utils_incl.glsl src/embedded_deps/debug_normal_frag.glsl debug_normal_frag.glsl src/embedded_deps/debug_normal_vert.glsl debug_normal_vert.glsl src/embedded_deps/debug_uv_frag.glsl debug_uv_frag.glsl src/embedded_deps/debug_uv_vert.glsl debug_uv_vert.glsl src/embedded_deps/light_incl.glsl light_incl.glsl src/embedded_deps/particles_frag.glsl particles_frag.glsl src/embedded_deps/particles_vert.glsl particles_vert.glsl src/embedded_deps/sprite_frag.glsl sprite_frag.glsl src/embedded_deps/sprite_vert.glsl sprite_vert.glsl src/embedded_deps/standard_pbr_frag.glsl standard_pbr_frag.glsl src/embedded_deps/standard_pbr_vert.glsl standard_pbr_vert.glsl src/embedded_deps/standard_blinn_phong_frag.glsl standard_blinn_phong_frag.glsl src/embedded_deps/standard_blinn_phong_vert.glsl standard_blinn_phong_vert.glsl src/embedded_deps/standard_phong_frag.glsl standard_phong_frag.glsl src/embedded_deps/standard_phong_vert.glsl standard_phong_vert.glsl src/embedded_deps/blit_frag.glsl blit_frag.glsl src/embedded_deps/blit_vert.glsl blit_vert.glsl src/embedded_deps/unlit_frag.glsl unlit_frag.glsl src/embedded_deps/unlit_vert.glsl unlit_vert.glsl src/embedded_deps/debug_tangent_frag.glsl debug_tangent_frag.glsl src/embedded_deps/debug_tangent_vert.glsl debug_tangent_vert.glsl src/embedded_deps/normalmap_incl.glsl normalmap_incl.glsl include/sre/impl/ShaderSource.inl +// files_to_cpp shader src/embedded_deps/sre_utils_incl.glsl sre_utils_incl.glsl src/embedded_deps/debug_normal_frag.glsl debug_normal_frag.glsl src/embedded_deps/debug_normal_vert.glsl debug_normal_vert.glsl src/embedded_deps/debug_uv_frag.glsl debug_uv_frag.glsl src/embedded_deps/debug_uv_vert.glsl debug_uv_vert.glsl src/embedded_deps/light_incl.glsl light_incl.glsl src/embedded_deps/particles_frag.glsl particles_frag.glsl src/embedded_deps/particles_vert.glsl particles_vert.glsl src/embedded_deps/sprite_frag.glsl sprite_frag.glsl src/embedded_deps/sprite_vert.glsl sprite_vert.glsl src/embedded_deps/standard_pbr_frag.glsl standard_pbr_frag.glsl src/embedded_deps/standard_pbr_vert.glsl standard_pbr_vert.glsl src/embedded_deps/standard_blinn_phong_frag.glsl standard_blinn_phong_frag.glsl src/embedded_deps/standard_blinn_phong_vert.glsl standard_blinn_phong_vert.glsl src/embedded_deps/standard_phong_frag.glsl standard_phong_frag.glsl src/embedded_deps/standard_phong_vert.glsl standard_phong_vert.glsl src/embedded_deps/blit_frag.glsl blit_frag.glsl src/embedded_deps/blit_vert.glsl blit_vert.glsl src/embedded_deps/unlit_frag.glsl unlit_frag.glsl src/embedded_deps/unlit_vert.glsl unlit_vert.glsl src/embedded_deps/debug_tangent_frag.glsl debug_tangent_frag.glsl src/embedded_deps/debug_tangent_vert.glsl debug_tangent_vert.glsl src/embedded_deps/normalmap_incl.glsl normalmap_incl.glsl src/embedded_deps/global_uniforms_incl.glsl global_uniforms_incl.glsl include/sre/impl/ShaderSource.inl #include #include #include @@ -51,9 +51,8 @@ in vec3 normal; out vec3 vNormal; uniform mat4 g_model; -uniform mat4 g_view; -uniform mat4 g_projection; uniform mat3 g_model_view_it; +#pragma include "global_uniforms_incl.glsl" void main(void) { gl_Position = g_projection * g_view * g_model * vec4(position,1.0); @@ -76,18 +75,15 @@ in vec4 uv; out vec4 vUV; uniform mat4 g_model; -uniform mat4 g_view; -uniform mat4 g_projection; +#pragma include "global_uniforms_incl.glsl" void main(void) { gl_Position = g_projection * g_view * g_model * vec4(position,1.0); vUV = uv; })"), -std::make_pair("light_incl.glsl",R"(uniform vec3 g_ambientLight; +std::make_pair("light_incl.glsl",R"( in vec4 vLightDir[SI_LIGHTS]; -uniform vec4 g_lightColorRange[SI_LIGHTS]; -uniform vec4 g_lightPosType[SI_LIGHTS]; uniform vec4 specularity; void lightDirectionAndAttenuation(vec4 lightPosType, float lightRange, vec3 pos, out vec3 lightDirection, out float attenuation){ @@ -188,11 +184,8 @@ out vec4 fragColor; in mat3 vUVMat; in vec3 uvSize; in vec4 vColor; -#ifdef GL_ES -uniform precision highp vec4 g_viewport; -#else -uniform vec4 g_viewport; -#endif + +#pragma include "global_uniforms_incl.glsl" uniform sampler2D tex; @@ -219,9 +212,7 @@ out vec4 vColor; out vec3 uvSize; uniform mat4 g_model; -uniform mat4 g_view; -uniform mat4 g_projection; -uniform vec4 g_viewport; +#pragma include "global_uniforms_incl.glsl" mat3 translate(vec2 p){ return mat3(1.0,0.0,0.0,0.0,1.0,0.0,p.x,p.y,1.0); @@ -273,8 +264,7 @@ out vec2 vUV; out vec4 vColor; uniform mat4 g_model; -uniform mat4 g_view; -uniform mat4 g_projection; +#pragma include "global_uniforms_incl.glsl" void main(void) { gl_Position = g_projection * g_view * g_model * vec4(position,1.0); @@ -295,7 +285,7 @@ in vec3 vWsPos; uniform vec4 color; uniform vec4 metallicRoughness; -uniform vec4 g_cameraPos; + uniform sampler2D tex; #ifdef S_METALROUGHNESSMAP uniform sampler2D mrTex; @@ -316,6 +306,7 @@ uniform float occlusionStrength; in vec4 vColor; #endif +#pragma include "global_uniforms_incl.glsl" #pragma include "normalmap_incl.glsl" #pragma include "light_incl.glsl" #pragma include "sre_utils_incl.glsl" @@ -424,7 +415,7 @@ void main(void) float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0); vec3 specularEnvironmentR0 = specularColor.rgb; vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90; - vec3 color = baseColor.rgb * g_ambientLight; // non pbr + vec3 color = baseColor.rgb * g_ambientLight.rgb; // non pbr vec3 n = getNormal(); // Normal at surface point vec3 v = normalize(g_cameraPos.xyz - vWsPos.xyz); // Vector from surface point to camera for (int i=0;i("global_uniforms_incl.glsl",R"(#if __VERSION__ > 100 +//layout(std140) uniform g_global_uniforms { +#endif +#ifdef GL_ES +uniform precision highp mat4 g_view; +uniform precision highp mat4 g_projection; +uniform precision highp vec4 g_viewport; +uniform precision highp vec4 g_cameraPos; +uniform precision highp vec4 g_ambientLight; +uniform precision highp vec4 g_lightColorRange[SI_LIGHTS]; +uniform precision highp vec4 g_lightPosType[SI_LIGHTS]; +#else +uniform mat4 g_view; +uniform mat4 g_projection; +uniform vec4 g_viewport; +uniform vec4 g_cameraPos; +uniform vec4 g_ambientLight; +uniform vec4 g_lightColorRange[SI_LIGHTS]; +uniform vec4 g_lightPosType[SI_LIGHTS]; +#endif + +#if __VERSION__ > 100 +//}; +#endif)"), }; \ No newline at end of file diff --git a/src/embedded_deps/blit_vert.glsl b/src/embedded_deps/blit_vert.glsl index 948f1393..be8b0c1b 100644 --- a/src/embedded_deps/blit_vert.glsl +++ b/src/embedded_deps/blit_vert.glsl @@ -9,8 +9,7 @@ in vec4 uv; out vec2 vUV; uniform mat4 g_model; -uniform mat4 g_view; -uniform mat4 g_projection; +#pragma include "global_uniforms_incl.glsl" void main(void) { gl_Position = g_model * vec4(position,1.0); diff --git a/src/embedded_deps/debug_normal_vert.glsl b/src/embedded_deps/debug_normal_vert.glsl index bfe3982a..b19afa51 100644 --- a/src/embedded_deps/debug_normal_vert.glsl +++ b/src/embedded_deps/debug_normal_vert.glsl @@ -4,9 +4,8 @@ in vec3 normal; out vec3 vNormal; uniform mat4 g_model; -uniform mat4 g_view; -uniform mat4 g_projection; uniform mat3 g_model_view_it; +#pragma include "global_uniforms_incl.glsl" void main(void) { gl_Position = g_projection * g_view * g_model * vec4(position,1.0); diff --git a/src/embedded_deps/debug_tangent_vert.glsl b/src/embedded_deps/debug_tangent_vert.glsl index d25344c6..061b3d7e 100644 --- a/src/embedded_deps/debug_tangent_vert.glsl +++ b/src/embedded_deps/debug_tangent_vert.glsl @@ -4,8 +4,7 @@ in vec4 tangent; out vec3 vTangent; uniform mat4 g_model; -uniform mat4 g_view; -uniform mat4 g_projection; +#pragma include "global_uniforms_incl.glsl" void main(void) { gl_Position = g_projection * g_view * g_model * vec4(position,1.0); diff --git a/src/embedded_deps/debug_uv_vert.glsl b/src/embedded_deps/debug_uv_vert.glsl index 83565db2..d7616483 100644 --- a/src/embedded_deps/debug_uv_vert.glsl +++ b/src/embedded_deps/debug_uv_vert.glsl @@ -4,8 +4,7 @@ in vec4 uv; out vec4 vUV; uniform mat4 g_model; -uniform mat4 g_view; -uniform mat4 g_projection; +#pragma include "global_uniforms_incl.glsl" void main(void) { gl_Position = g_projection * g_view * g_model * vec4(position,1.0); diff --git a/src/embedded_deps/global_uniforms_incl.glsl b/src/embedded_deps/global_uniforms_incl.glsl new file mode 100644 index 00000000..4bd9b7aa --- /dev/null +++ b/src/embedded_deps/global_uniforms_incl.glsl @@ -0,0 +1,24 @@ +#if __VERSION__ > 100 +//layout(std140) uniform g_global_uniforms { +#endif +#ifdef GL_ES +uniform precision highp mat4 g_view; +uniform precision highp mat4 g_projection; +uniform precision highp vec4 g_viewport; +uniform precision highp vec4 g_cameraPos; +uniform precision highp vec4 g_ambientLight; +uniform precision highp vec4 g_lightColorRange[SI_LIGHTS]; +uniform precision highp vec4 g_lightPosType[SI_LIGHTS]; +#else +uniform mat4 g_view; +uniform mat4 g_projection; +uniform vec4 g_viewport; +uniform vec4 g_cameraPos; +uniform vec4 g_ambientLight; +uniform vec4 g_lightColorRange[SI_LIGHTS]; +uniform vec4 g_lightPosType[SI_LIGHTS]; +#endif + +#if __VERSION__ > 100 +//}; +#endif \ No newline at end of file diff --git a/src/embedded_deps/light_incl.glsl b/src/embedded_deps/light_incl.glsl index 0d9c97b9..b7a61667 100644 --- a/src/embedded_deps/light_incl.glsl +++ b/src/embedded_deps/light_incl.glsl @@ -1,8 +1,6 @@ -uniform vec3 g_ambientLight; + in vec4 vLightDir[SI_LIGHTS]; -uniform vec4 g_lightColorRange[SI_LIGHTS]; -uniform vec4 g_lightPosType[SI_LIGHTS]; uniform vec4 specularity; void lightDirectionAndAttenuation(vec4 lightPosType, float lightRange, vec3 pos, out vec3 lightDirection, out float attenuation){ diff --git a/src/embedded_deps/particles_frag.glsl b/src/embedded_deps/particles_frag.glsl index 4e0fda28..55f1a18f 100644 --- a/src/embedded_deps/particles_frag.glsl +++ b/src/embedded_deps/particles_frag.glsl @@ -3,11 +3,8 @@ out vec4 fragColor; in mat3 vUVMat; in vec3 uvSize; in vec4 vColor; -#ifdef GL_ES -uniform precision highp vec4 g_viewport; -#else -uniform vec4 g_viewport; -#endif + +#pragma include "global_uniforms_incl.glsl" uniform sampler2D tex; diff --git a/src/embedded_deps/particles_vert.glsl b/src/embedded_deps/particles_vert.glsl index bbd08ef8..b1032ac0 100644 --- a/src/embedded_deps/particles_vert.glsl +++ b/src/embedded_deps/particles_vert.glsl @@ -8,9 +8,7 @@ out vec4 vColor; out vec3 uvSize; uniform mat4 g_model; -uniform mat4 g_view; -uniform mat4 g_projection; -uniform vec4 g_viewport; +#pragma include "global_uniforms_incl.glsl" mat3 translate(vec2 p){ return mat3(1.0,0.0,0.0,0.0,1.0,0.0,p.x,p.y,1.0); diff --git a/src/embedded_deps/sprite_vert.glsl b/src/embedded_deps/sprite_vert.glsl index 74e9d485..6008c321 100644 --- a/src/embedded_deps/sprite_vert.glsl +++ b/src/embedded_deps/sprite_vert.glsl @@ -6,8 +6,7 @@ out vec2 vUV; out vec4 vColor; uniform mat4 g_model; -uniform mat4 g_view; -uniform mat4 g_projection; +#pragma include "global_uniforms_incl.glsl" void main(void) { gl_Position = g_projection * g_view * g_model * vec4(position,1.0); diff --git a/src/embedded_deps/standard_blinn_phong_frag.glsl b/src/embedded_deps/standard_blinn_phong_frag.glsl index 8bfa5350..574ecf8d 100644 --- a/src/embedded_deps/standard_blinn_phong_frag.glsl +++ b/src/embedded_deps/standard_blinn_phong_frag.glsl @@ -7,7 +7,6 @@ in vec3 vNormal; #endif in vec2 vUV; in vec3 vWsPos; -uniform vec4 g_cameraPos; #ifdef S_NORMALMAP uniform sampler2D normalTex; uniform float normalScale; @@ -19,6 +18,7 @@ in vec4 vColor; uniform vec4 color; uniform sampler2D tex; +#pragma include "global_uniforms_incl.glsl" #pragma include "light_incl.glsl" #pragma include "normalmap_incl.glsl" #pragma include "sre_utils_incl.glsl" diff --git a/src/embedded_deps/standard_blinn_phong_vert.glsl b/src/embedded_deps/standard_blinn_phong_vert.glsl index e579b80a..1e15ae32 100644 --- a/src/embedded_deps/standard_blinn_phong_vert.glsl +++ b/src/embedded_deps/standard_blinn_phong_vert.glsl @@ -16,10 +16,9 @@ out vec4 vColor; #endif uniform mat4 g_model; -uniform mat4 g_view; -uniform mat4 g_projection; uniform mat3 g_model_it; +#pragma include "global_uniforms_incl.glsl" #pragma include "normalmap_incl.glsl" void main(void) { diff --git a/src/embedded_deps/standard_pbr_frag.glsl b/src/embedded_deps/standard_pbr_frag.glsl index fb482a9a..06bd3a66 100644 --- a/src/embedded_deps/standard_pbr_frag.glsl +++ b/src/embedded_deps/standard_pbr_frag.glsl @@ -12,7 +12,7 @@ in vec3 vWsPos; uniform vec4 color; uniform vec4 metallicRoughness; -uniform vec4 g_cameraPos; + uniform sampler2D tex; #ifdef S_METALROUGHNESSMAP uniform sampler2D mrTex; @@ -33,6 +33,7 @@ uniform float occlusionStrength; in vec4 vColor; #endif +#pragma include "global_uniforms_incl.glsl" #pragma include "normalmap_incl.glsl" #pragma include "light_incl.glsl" #pragma include "sre_utils_incl.glsl" @@ -141,7 +142,7 @@ void main(void) float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0); vec3 specularEnvironmentR0 = specularColor.rgb; vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90; - vec3 color = baseColor.rgb * g_ambientLight; // non pbr + vec3 color = baseColor.rgb * g_ambientLight.rgb; // non pbr vec3 n = getNormal(); // Normal at surface point vec3 v = normalize(g_cameraPos.xyz - vWsPos.xyz); // Vector from surface point to camera for (int i=0;iambientLight)); + glUniform4fv(uniformLocationAmbientLight, 1, glm::value_ptr(worldLights->ambientLight)); } if (uniformLocationLightPosType != -1 && uniformLocationLightColorRange != -1){ std::vector lightPosType(maxSceneLights, glm::vec4(0)); diff --git a/src/sre/WorldLights.cpp b/src/sre/WorldLights.cpp index 45b68834..838f8bad 100755 --- a/src/sre/WorldLights.cpp +++ b/src/sre/WorldLights.cpp @@ -40,11 +40,11 @@ namespace sre { } void WorldLights::setAmbientLight(const glm::vec3& ambientLight){ - this->ambientLight = ambientLight; + this->ambientLight = glm::vec4(ambientLight,0.0); } glm::vec3 WorldLights::getAmbientLight() { - return ambientLight; + return glm::vec3(ambientLight); } void WorldLights::clear() { From d85a51a52e1b941c530eccfc2c78afc36c0bfd65 Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Sun, 18 Mar 2018 22:32:40 +0100 Subject: [PATCH 08/16] Use shared uniform --- include/sre/RenderPass.hpp | 11 +++ include/sre/Renderer.hpp | 5 ++ include/sre/impl/ShaderSource.inl | 45 +++++------ src/embedded_deps/blit_frag.glsl | 2 +- src/embedded_deps/blit_vert.glsl | 2 +- src/embedded_deps/debug_normal_frag.glsl | 2 +- src/embedded_deps/debug_normal_vert.glsl | 2 +- src/embedded_deps/debug_tangent_frag.glsl | 2 +- src/embedded_deps/debug_tangent_vert.glsl | 2 +- src/embedded_deps/debug_uv_frag.glsl | 2 +- src/embedded_deps/debug_uv_vert.glsl | 2 +- src/embedded_deps/global_uniforms_incl.glsl | 5 +- src/embedded_deps/particles_frag.glsl | 2 +- src/embedded_deps/particles_vert.glsl | 2 +- src/embedded_deps/sprite_frag.glsl | 2 +- src/embedded_deps/sprite_vert.glsl | 2 +- .../standard_blinn_phong_frag.glsl | 2 +- .../standard_blinn_phong_vert.glsl | 2 +- src/embedded_deps/standard_pbr_frag.glsl | 2 +- src/embedded_deps/standard_pbr_vert.glsl | 2 +- src/embedded_deps/standard_phong_frag.glsl | 2 +- src/embedded_deps/standard_phong_vert.glsl | 2 +- src/embedded_deps/unlit_frag.glsl | 2 +- src/embedded_deps/unlit_vert.glsl | 2 +- src/imgui/imgui_sre.cpp | 4 +- src/sre/RenderPass.cpp | 81 ++++++++++++++++--- src/sre/Renderer.cpp | 16 ++++ src/sre/Shader.cpp | 14 +++- test/custom-mesh-layout-default-values.cpp | 4 +- 29 files changed, 162 insertions(+), 63 deletions(-) diff --git a/include/sre/RenderPass.hpp b/include/sre/RenderPass.hpp index 02223c4a..bb7d1d6b 100755 --- a/include/sre/RenderPass.hpp +++ b/include/sre/RenderPass.hpp @@ -126,6 +126,15 @@ namespace sre { glm::mat4 modelTransform; std::vector> materials; }; + struct GlobalUniforms{ + glm::mat4* g_view; + glm::mat4* g_projection; + glm::vec4* g_viewport; + glm::vec4* g_cameraPos; + glm::vec4* g_ambientLight; + glm::vec4* g_lightColorRange; + glm::vec4* g_lightPosType; + }; std::vector renderQueue; void drawInstance(RenderQueueObj& rqObj); // perform the actual rendering @@ -134,6 +143,8 @@ namespace sre { explicit RenderPass(RenderPass::RenderPassBuilder& builder); void setupShaderRenderPass(Shader *shader); + void setupShaderRenderPass(const GlobalUniforms& globalUniforms); + void setupGlobalShaderUniforms(); void setupShader(const glm::mat4 &modelTransform, Shader *shader); Shader* lastBoundShader = nullptr; diff --git a/include/sre/Renderer.hpp b/include/sre/Renderer.hpp index e73126b4..390a5493 100755 --- a/include/sre/Renderer.hpp +++ b/include/sre/Renderer.hpp @@ -107,6 +107,11 @@ namespace sre { std::vector textures; std::vector spriteAtlases; + void initGlobalUniformBuffer(); + GLuint globalUniformBuffer; + GLuint globalUniformBufferSize = 0; + + VR* vr = nullptr; friend class Mesh; diff --git a/include/sre/impl/ShaderSource.inl b/include/sre/impl/ShaderSource.inl index ac9bd6e4..f2edb90b 100644 --- a/include/sre/impl/ShaderSource.inl +++ b/include/sre/impl/ShaderSource.inl @@ -34,7 +34,7 @@ vec4 toOutput(vec3 colorLinear, float alpha){ return vec4(colorLinear, alpha); // pass through #endif })"), -std::make_pair("debug_normal_frag.glsl",R"(#version 140 +std::make_pair("debug_normal_frag.glsl",R"(#version 330 out vec4 fragColor; in vec3 vNormal; @@ -45,7 +45,7 @@ void main(void) fragColor = vec4(vNormal*0.5+0.5,1.0); fragColor = toOutput(fragColor); })"), -std::make_pair("debug_normal_vert.glsl",R"(#version 140 +std::make_pair("debug_normal_vert.glsl",R"(#version 330 in vec3 position; in vec3 normal; out vec3 vNormal; @@ -58,7 +58,7 @@ void main(void) { gl_Position = g_projection * g_view * g_model * vec4(position,1.0); vNormal = normal; })"), -std::make_pair("debug_uv_frag.glsl",R"(#version 140 +std::make_pair("debug_uv_frag.glsl",R"(#version 330 out vec4 fragColor; in vec4 vUV; @@ -69,7 +69,7 @@ void main(void) fragColor = vUV; fragColor = toOutput(fragColor); })"), -std::make_pair("debug_uv_vert.glsl",R"(#version 140 +std::make_pair("debug_uv_vert.glsl",R"(#version 330 in vec3 position; in vec4 uv; out vec4 vUV; @@ -179,7 +179,7 @@ vec3 computeLightPhong(vec3 wsPos, vec3 wsCameraPos, vec3 normal, out vec3 specu return lightColor; })"), -std::make_pair("particles_frag.glsl",R"(#version 140 +std::make_pair("particles_frag.glsl",R"(#version 330 out vec4 fragColor; in mat3 vUVMat; in vec3 uvSize; @@ -202,7 +202,7 @@ void main(void) fragColor = c; fragColor = toOutput(fragColor); })"), -std::make_pair("particles_vert.glsl",R"(#version 140 +std::make_pair("particles_vert.glsl",R"(#version 330 in vec3 position; in float particleSize; in vec4 uv; @@ -242,7 +242,7 @@ void main(void) { vColor = color; uvSize = uv.xyz; })"), -std::make_pair("sprite_frag.glsl",R"(#version 140 +std::make_pair("sprite_frag.glsl",R"(#version 330 out vec4 fragColor; in vec2 vUV; in vec4 vColor; @@ -256,7 +256,7 @@ void main(void) fragColor = vColor * toLinear(texture(tex, vUV)); fragColor = toOutput(fragColor); })"), -std::make_pair("sprite_vert.glsl",R"(#version 140 +std::make_pair("sprite_vert.glsl",R"(#version 330 in vec3 position; in vec4 uv; in vec4 color; @@ -271,7 +271,7 @@ void main(void) { vUV = uv.xy; vColor = color; })"), -std::make_pair("standard_pbr_frag.glsl",R"(#version 140 +std::make_pair("standard_pbr_frag.glsl",R"(#version 330 #extension GL_EXT_shader_texture_lod: enable #extension GL_OES_standard_derivatives : enable out vec4 fragColor; @@ -473,7 +473,7 @@ void main(void) fragColor = toOutput(color,baseColor.a); })"), -std::make_pair("standard_pbr_vert.glsl",R"(#version 140 +std::make_pair("standard_pbr_vert.glsl",R"(#version 330 in vec3 position; in vec3 normal; in vec4 uv; @@ -510,7 +510,7 @@ void main(void) { vColor = color; #endif })"), -std::make_pair("standard_blinn_phong_frag.glsl",R"(#version 140 +std::make_pair("standard_blinn_phong_frag.glsl",R"(#version 330 out vec4 fragColor; #if defined(S_TANGENTS) && defined(S_NORMALMAP) in mat3 vTBN; @@ -548,7 +548,7 @@ void main() fragColor = c * vec4(l, 1.0) + vec4(specularLight,0); fragColor = toOutput(fragColor); })"), -std::make_pair("standard_blinn_phong_vert.glsl",R"(#version 140 +std::make_pair("standard_blinn_phong_vert.glsl",R"(#version 330 in vec3 position; in vec3 normal; in vec4 uv; @@ -586,7 +586,7 @@ void main(void) { vColor = color; #endif })"), -std::make_pair("standard_phong_frag.glsl",R"(#version 140 +std::make_pair("standard_phong_frag.glsl",R"(#version 330 out vec4 fragColor; #if defined(S_TANGENTS) && defined(S_NORMALMAP) in mat3 vTBN; @@ -625,7 +625,7 @@ void main() fragColor = c * vec4(l, 1.0) + vec4(specularLight,0); fragColor = toOutput(fragColor); })"), -std::make_pair("standard_phong_vert.glsl",R"(#version 140 +std::make_pair("standard_phong_vert.glsl",R"(#version 330 in vec3 position; in vec3 normal; in vec4 uv; @@ -665,7 +665,7 @@ void main(void) { vColor = color; #endif })"), -std::make_pair("blit_frag.glsl",R"(#version 140 +std::make_pair("blit_frag.glsl",R"(#version 330 out vec4 fragColor; in vec2 vUV; @@ -678,7 +678,7 @@ void main(void) fragColor = toLinear(texture(tex, vUV)); fragColor = toOutput(fragColor); })"), -std::make_pair("blit_vert.glsl",R"(#version 140 +std::make_pair("blit_vert.glsl",R"(#version 330 in vec3 position; in vec3 normal; #ifdef S_VERTEX_COLOR @@ -695,7 +695,7 @@ void main(void) { gl_Position = g_model * vec4(position,1.0); vUV = uv.xy; })"), -std::make_pair("unlit_frag.glsl",R"(#version 140 +std::make_pair("unlit_frag.glsl",R"(#version 330 out vec4 fragColor; in vec2 vUV; #ifdef S_VERTEX_COLOR @@ -715,7 +715,7 @@ void main(void) #endif fragColor = toOutput(fragColor); })"), -std::make_pair("unlit_vert.glsl",R"(#version 140 +std::make_pair("unlit_vert.glsl",R"(#version 330 in vec3 position; in vec3 normal; #ifdef S_VERTEX_COLOR @@ -735,7 +735,7 @@ void main(void) { vColor = color; #endif })"), -std::make_pair("debug_tangent_frag.glsl",R"(#version 140 +std::make_pair("debug_tangent_frag.glsl",R"(#version 330 out vec4 fragColor; in vec3 vTangent; @@ -746,7 +746,7 @@ void main(void) fragColor = vec4(vTangent*0.5+0.5,1.0); fragColor = toOutput(fragColor); })"), -std::make_pair("debug_tangent_vert.glsl",R"(#version 140 +std::make_pair("debug_tangent_vert.glsl",R"(#version 330 in vec3 position; in vec4 tangent; out vec3 vTangent; @@ -800,7 +800,7 @@ vec3 getNormal() } #endif)"), std::make_pair("global_uniforms_incl.glsl",R"(#if __VERSION__ > 100 -//layout(std140) uniform g_global_uniforms { +layout(std140) uniform g_global_uniforms { #endif #ifdef GL_ES uniform precision highp mat4 g_view; @@ -819,8 +819,7 @@ uniform vec4 g_ambientLight; uniform vec4 g_lightColorRange[SI_LIGHTS]; uniform vec4 g_lightPosType[SI_LIGHTS]; #endif - #if __VERSION__ > 100 -//}; +}; #endif)"), }; \ No newline at end of file diff --git a/src/embedded_deps/blit_frag.glsl b/src/embedded_deps/blit_frag.glsl index 9d3e2039..6a612e54 100644 --- a/src/embedded_deps/blit_frag.glsl +++ b/src/embedded_deps/blit_frag.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 out vec4 fragColor; in vec2 vUV; diff --git a/src/embedded_deps/blit_vert.glsl b/src/embedded_deps/blit_vert.glsl index be8b0c1b..def545e3 100644 --- a/src/embedded_deps/blit_vert.glsl +++ b/src/embedded_deps/blit_vert.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 in vec3 position; in vec3 normal; #ifdef S_VERTEX_COLOR diff --git a/src/embedded_deps/debug_normal_frag.glsl b/src/embedded_deps/debug_normal_frag.glsl index 2c905942..22d20750 100644 --- a/src/embedded_deps/debug_normal_frag.glsl +++ b/src/embedded_deps/debug_normal_frag.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 out vec4 fragColor; in vec3 vNormal; diff --git a/src/embedded_deps/debug_normal_vert.glsl b/src/embedded_deps/debug_normal_vert.glsl index b19afa51..ae08c332 100644 --- a/src/embedded_deps/debug_normal_vert.glsl +++ b/src/embedded_deps/debug_normal_vert.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 in vec3 position; in vec3 normal; out vec3 vNormal; diff --git a/src/embedded_deps/debug_tangent_frag.glsl b/src/embedded_deps/debug_tangent_frag.glsl index b32c351f..b373aabf 100644 --- a/src/embedded_deps/debug_tangent_frag.glsl +++ b/src/embedded_deps/debug_tangent_frag.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 out vec4 fragColor; in vec3 vTangent; diff --git a/src/embedded_deps/debug_tangent_vert.glsl b/src/embedded_deps/debug_tangent_vert.glsl index 061b3d7e..ed5d397e 100644 --- a/src/embedded_deps/debug_tangent_vert.glsl +++ b/src/embedded_deps/debug_tangent_vert.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 in vec3 position; in vec4 tangent; out vec3 vTangent; diff --git a/src/embedded_deps/debug_uv_frag.glsl b/src/embedded_deps/debug_uv_frag.glsl index ce170f71..0dd70d77 100644 --- a/src/embedded_deps/debug_uv_frag.glsl +++ b/src/embedded_deps/debug_uv_frag.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 out vec4 fragColor; in vec4 vUV; diff --git a/src/embedded_deps/debug_uv_vert.glsl b/src/embedded_deps/debug_uv_vert.glsl index d7616483..86c7fa7a 100644 --- a/src/embedded_deps/debug_uv_vert.glsl +++ b/src/embedded_deps/debug_uv_vert.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 in vec3 position; in vec4 uv; out vec4 vUV; diff --git a/src/embedded_deps/global_uniforms_incl.glsl b/src/embedded_deps/global_uniforms_incl.glsl index 4bd9b7aa..f7768bd5 100644 --- a/src/embedded_deps/global_uniforms_incl.glsl +++ b/src/embedded_deps/global_uniforms_incl.glsl @@ -1,5 +1,5 @@ #if __VERSION__ > 100 -//layout(std140) uniform g_global_uniforms { +layout(std140) uniform g_global_uniforms { #endif #ifdef GL_ES uniform precision highp mat4 g_view; @@ -18,7 +18,6 @@ uniform vec4 g_ambientLight; uniform vec4 g_lightColorRange[SI_LIGHTS]; uniform vec4 g_lightPosType[SI_LIGHTS]; #endif - #if __VERSION__ > 100 -//}; +}; #endif \ No newline at end of file diff --git a/src/embedded_deps/particles_frag.glsl b/src/embedded_deps/particles_frag.glsl index 55f1a18f..5e467480 100644 --- a/src/embedded_deps/particles_frag.glsl +++ b/src/embedded_deps/particles_frag.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 out vec4 fragColor; in mat3 vUVMat; in vec3 uvSize; diff --git a/src/embedded_deps/particles_vert.glsl b/src/embedded_deps/particles_vert.glsl index b1032ac0..4d52f116 100644 --- a/src/embedded_deps/particles_vert.glsl +++ b/src/embedded_deps/particles_vert.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 in vec3 position; in float particleSize; in vec4 uv; diff --git a/src/embedded_deps/sprite_frag.glsl b/src/embedded_deps/sprite_frag.glsl index 8571720b..1cf68866 100644 --- a/src/embedded_deps/sprite_frag.glsl +++ b/src/embedded_deps/sprite_frag.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 out vec4 fragColor; in vec2 vUV; in vec4 vColor; diff --git a/src/embedded_deps/sprite_vert.glsl b/src/embedded_deps/sprite_vert.glsl index 6008c321..e9bccaf6 100644 --- a/src/embedded_deps/sprite_vert.glsl +++ b/src/embedded_deps/sprite_vert.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 in vec3 position; in vec4 uv; in vec4 color; diff --git a/src/embedded_deps/standard_blinn_phong_frag.glsl b/src/embedded_deps/standard_blinn_phong_frag.glsl index 574ecf8d..3226b68e 100644 --- a/src/embedded_deps/standard_blinn_phong_frag.glsl +++ b/src/embedded_deps/standard_blinn_phong_frag.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 out vec4 fragColor; #if defined(S_TANGENTS) && defined(S_NORMALMAP) in mat3 vTBN; diff --git a/src/embedded_deps/standard_blinn_phong_vert.glsl b/src/embedded_deps/standard_blinn_phong_vert.glsl index 1e15ae32..68dc6d14 100644 --- a/src/embedded_deps/standard_blinn_phong_vert.glsl +++ b/src/embedded_deps/standard_blinn_phong_vert.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 in vec3 position; in vec3 normal; in vec4 uv; diff --git a/src/embedded_deps/standard_pbr_frag.glsl b/src/embedded_deps/standard_pbr_frag.glsl index 06bd3a66..393f699d 100644 --- a/src/embedded_deps/standard_pbr_frag.glsl +++ b/src/embedded_deps/standard_pbr_frag.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 #extension GL_EXT_shader_texture_lod: enable #extension GL_OES_standard_derivatives : enable out vec4 fragColor; diff --git a/src/embedded_deps/standard_pbr_vert.glsl b/src/embedded_deps/standard_pbr_vert.glsl index d32de66e..d9cce4ba 100644 --- a/src/embedded_deps/standard_pbr_vert.glsl +++ b/src/embedded_deps/standard_pbr_vert.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 in vec3 position; in vec3 normal; in vec4 uv; diff --git a/src/embedded_deps/standard_phong_frag.glsl b/src/embedded_deps/standard_phong_frag.glsl index 0609cc09..af954e40 100644 --- a/src/embedded_deps/standard_phong_frag.glsl +++ b/src/embedded_deps/standard_phong_frag.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 out vec4 fragColor; #if defined(S_TANGENTS) && defined(S_NORMALMAP) in mat3 vTBN; diff --git a/src/embedded_deps/standard_phong_vert.glsl b/src/embedded_deps/standard_phong_vert.glsl index bcbee499..dae5a9fb 100644 --- a/src/embedded_deps/standard_phong_vert.glsl +++ b/src/embedded_deps/standard_phong_vert.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 in vec3 position; in vec3 normal; in vec4 uv; diff --git a/src/embedded_deps/unlit_frag.glsl b/src/embedded_deps/unlit_frag.glsl index 8e8c114d..930bfd6c 100644 --- a/src/embedded_deps/unlit_frag.glsl +++ b/src/embedded_deps/unlit_frag.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 out vec4 fragColor; in vec2 vUV; #ifdef S_VERTEX_COLOR diff --git a/src/embedded_deps/unlit_vert.glsl b/src/embedded_deps/unlit_vert.glsl index bf190fe6..b991a2fa 100644 --- a/src/embedded_deps/unlit_vert.glsl +++ b/src/embedded_deps/unlit_vert.glsl @@ -1,4 +1,4 @@ -#version 140 +#version 330 in vec3 position; in vec3 normal; #ifdef S_VERTEX_COLOR diff --git a/src/imgui/imgui_sre.cpp b/src/imgui/imgui_sre.cpp index 089f794f..963f1d97 100755 --- a/src/imgui/imgui_sre.cpp +++ b/src/imgui/imgui_sre.cpp @@ -269,7 +269,7 @@ bool ImGui_SRE_CreateDeviceObjects() glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); } const GLchar *vertex_shader = - "#version 140\n" + "#version 330\n" "uniform mat4 ProjMtx;\n" "in vec2 Position;\n" "in vec2 UV;\n" @@ -284,7 +284,7 @@ bool ImGui_SRE_CreateDeviceObjects() "}\n"; std::stringstream ss; - ss << "#version 140\n"; + ss << "#version 330\n"; ss << "uniform sampler2D Texture;\n"; ss << "in vec2 Frag_UV;\n"; ss << "in vec4 Frag_Color;\n"; diff --git a/src/sre/RenderPass.cpp b/src/sre/RenderPass.cpp index 69bad221..ad3869dc 100755 --- a/src/sre/RenderPass.cpp +++ b/src/sre/RenderPass.cpp @@ -149,6 +149,37 @@ namespace sre { shader->setLights(builder.worldLights); } + void RenderPass::setupShaderRenderPass(const RenderPass::GlobalUniforms &globalUniforms) { + *globalUniforms.g_view = builder.camera.viewTransform; + *globalUniforms.g_projection = projection; + *globalUniforms.g_viewport = glm::vec4 ((float)viewportSize.x,(float)viewportSize.y,(float)viewportOffset.x,(float)viewportOffset.y);; + *globalUniforms.g_cameraPos = glm::vec4(this->builder.camera.getPosition(),1.0f);; + int maxSceneLights = Renderer::instance->maxSceneLights; + size_t lightSize = sizeof(glm::vec4)*(1 + maxSceneLights*2); + memset(globalUniforms.g_ambientLight,0, lightSize); // ambient + (lightPosType + lightColorRange) * maxSceneLights + if (builder.worldLights){ + *globalUniforms.g_ambientLight = glm::vec4(builder.worldLights->getAmbientLight(),1.0); + + for (int i=0;igetLight(i); + if (light == nullptr || light->lightType == LightType::Unused) { + globalUniforms.g_lightPosType[i] = glm::vec4(0.0f,0.0f,0.0f, 2); + + continue; + } else if (light->lightType == LightType::Point) { + globalUniforms.g_lightPosType[i] = glm::vec4(light->position, 1); + } else if (light->lightType == LightType::Directional) { + globalUniforms.g_lightPosType[i] = glm::vec4(glm::normalize(light->direction), 0); + } + // transform to eye space + globalUniforms.g_lightColorRange[i] = glm::vec4(light->color, light->range); + } + } + glBindBuffer(GL_UNIFORM_BUFFER, Renderer::instance->globalUniformBuffer); + glBufferData(GL_UNIFORM_BUFFER, Renderer::instance->globalUniformBufferSize, globalUniforms.g_view, GL_STREAM_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + void RenderPass::setupShader(const glm::mat4 &modelTransform, Shader *shader) { if (lastBoundShader != shader){ builder.renderStats->stateChangesShader++; @@ -188,6 +219,41 @@ namespace sre { }); } + void RenderPass::setupGlobalShaderUniforms(){ + static std::vector buffer; + static GlobalUniforms globalUniforms; + static bool once = [&](){ + buffer.resize(Renderer::instance->globalUniformBufferSize, 0); + globalUniforms.g_view = reinterpret_cast(buffer.data()); + globalUniforms.g_projection = reinterpret_cast(buffer.data() + sizeof(glm::mat4)); + globalUniforms.g_viewport = reinterpret_cast(buffer.data() + sizeof(glm::mat4)*2); + globalUniforms.g_cameraPos = reinterpret_cast(buffer.data() + sizeof(glm::mat4)*2 + sizeof(glm::vec4)); + globalUniforms.g_ambientLight = reinterpret_cast(buffer.data() + sizeof(glm::mat4)*2 + sizeof(glm::vec4)*2); + int lightColorRangeOffset = sizeof(glm::mat4)*2 + sizeof(glm::vec4)*3; + globalUniforms.g_lightColorRange = reinterpret_cast(buffer.data() + lightColorRangeOffset); + int g_lightPosTypeOffset = lightColorRangeOffset+ sizeof(glm::vec4)*(Renderer::instance->maxSceneLights); + globalUniforms.g_lightPosType = reinterpret_cast(buffer.data() + g_lightPosTypeOffset ); + return true; + } (); + auto rinfo = renderInfo(); + if (rinfo.graphicsAPIVersionMajor <= 2){ + // find list of used shaders + shaders.clear(); + for (auto & rqObj : renderQueue){ + for (auto & mat : rqObj.materials){ + shaders.insert(mat->getShader().get()); + } + } + // update global uniforms + for (auto shader : shaders){ + glUseProgram(shader->shaderProgramId); + setupShaderRenderPass(shader); + } + } else { + setupShaderRenderPass(globalUniforms); + } + } + void RenderPass::finish(){ if (mIsFinished){ return; @@ -230,18 +296,7 @@ namespace sre { projection = builder.camera.getProjectionTransform(viewportSize); - // find list of used shaders - shaders.clear(); - for (auto & rqObj : renderQueue){ - for (auto & mat : rqObj.materials){ - shaders.insert(mat->getShader().get()); - } - } - // update global uniforms - for (auto shader : shaders){ - glUseProgram(shader->shaderProgramId); - setupShaderRenderPass(shader); - } + setupGlobalShaderUniforms(); for (auto & rqObj : renderQueue){ drawInstance(rqObj); @@ -373,4 +428,6 @@ namespace sre { draw(mesh, transformation, material); } + + } diff --git a/src/sre/Renderer.cpp b/src/sre/Renderer.cpp index 04b0111d..04df911f 100755 --- a/src/sre/Renderer.cpp +++ b/src/sre/Renderer.cpp @@ -114,6 +114,8 @@ namespace sre { glEnable(GL_POINT_SPRITE); } + initGlobalUniformBuffer(); + // initialize ImGUI ImGui_SRE_Init(window); @@ -123,6 +125,7 @@ namespace sre { Renderer::~Renderer() { delete vr; + glDeleteBuffers(1,&globalUniformBuffer); SDL_GL_DeleteContext(glcontext); instance = nullptr; } @@ -170,4 +173,17 @@ namespace sre { const RenderInfo &Renderer::getRenderInfo() { return renderInfo_; } + + void Renderer::initGlobalUniformBuffer(){ + if (renderInfo_.graphicsAPIVersionMajor <= 2){ + globalUniformBuffer = 0; + return; // + } + glGenBuffers(1,&globalUniformBuffer); + size_t lightSize = sizeof(glm::vec4)*(1 + maxSceneLights*2); + globalUniformBufferSize = sizeof(glm::mat4)*2+sizeof(glm::vec4)*2 + lightSize; + glBindBuffer(GL_UNIFORM_BUFFER, globalUniformBuffer); + glBufferData(GL_UNIFORM_BUFFER, globalUniformBufferSize, NULL, GL_STREAM_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } } diff --git a/src/sre/Shader.cpp b/src/sre/Shader.cpp index f6e7947c..a7ddba94 100755 --- a/src/sre/Shader.cpp +++ b/src/sre/Shader.cpp @@ -275,7 +275,7 @@ namespace sre { std::string Shader::translateToGLSLES(std::string source, bool vertexShader, int version) { using namespace std; - string replace = "#version 140"; + string replace = "#version 330"; string replaceWith = string("#version ")+std::to_string(version); if (version >100){ replaceWith += " es"; @@ -758,6 +758,18 @@ namespace sre { if (oldShaderProgramId != 0){ glDeleteProgram( oldShaderProgramId ); // delete old shader if any } + // setup global uniform + glUseProgram(shaderProgramId); + auto index = glGetUniformBlockIndex(shaderProgramId, "g_global_uniforms"); + if (index != GL_INVALID_INDEX){ + const int globalUniformBindingIndex = 1; + glUniformBlockBinding(shaderProgramId, index, globalUniformBindingIndex); + glBindBufferRange(GL_UNIFORM_BUFFER, globalUniformBindingIndex, + Renderer::instance->globalUniformBuffer, 0, Renderer::instance->globalUniformBufferSize); + } else { + + } + updateUniformsAndAttributes(); return true; } diff --git a/test/custom-mesh-layout-default-values.cpp b/test/custom-mesh-layout-default-values.cpp index d926a6c5..5e2a49f8 100644 --- a/test/custom-mesh-layout-default-values.cpp +++ b/test/custom-mesh-layout-default-values.cpp @@ -34,7 +34,7 @@ class CustomMeshLayoutExample{ .withAttribute("color",colors) .build(); - std::string vertexShaderSource = R"(#version 140 + std::string vertexShaderSource = R"(#version 330 in vec4 posxyzw; // should automatically cast vec2 -> vec4 by appending (z = 0.0, w = 1.0) in vec4 color; out vec4 vColor; @@ -48,7 +48,7 @@ void main(void) { vColor = color; } )"; - std::string fragmentShaderSource = R"(#version 140 + std::string fragmentShaderSource = R"(#version 330 out vec4 fragColor; in vec4 vColor; From 8c10d3800232f29a8ceb2eaa2dc692131796b5ef Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Sun, 18 Mar 2018 23:03:09 +0100 Subject: [PATCH 09/16] Use shared uniform --- include/sre/Renderer.hpp | 2 +- src/sre/RenderPass.cpp | 9 ++++----- src/sre/Shader.cpp | 18 +++++++++--------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/include/sre/Renderer.hpp b/include/sre/Renderer.hpp index 390a5493..623a0b0e 100755 --- a/include/sre/Renderer.hpp +++ b/include/sre/Renderer.hpp @@ -108,7 +108,7 @@ namespace sre { std::vector spriteAtlases; void initGlobalUniformBuffer(); - GLuint globalUniformBuffer; + GLuint globalUniformBuffer = 0; GLuint globalUniformBufferSize = 0; diff --git a/src/sre/RenderPass.cpp b/src/sre/RenderPass.cpp index ad3869dc..1748fbac 100755 --- a/src/sre/RenderPass.cpp +++ b/src/sre/RenderPass.cpp @@ -223,6 +223,7 @@ namespace sre { static std::vector buffer; static GlobalUniforms globalUniforms; static bool once = [&](){ + // allocate buffer and setup pointers into buffer buffer.resize(Renderer::instance->globalUniformBufferSize, 0); globalUniforms.g_view = reinterpret_cast(buffer.data()); globalUniforms.g_projection = reinterpret_cast(buffer.data() + sizeof(glm::mat4)); @@ -236,7 +237,9 @@ namespace sre { return true; } (); auto rinfo = renderInfo(); - if (rinfo.graphicsAPIVersionMajor <= 2){ + if (Renderer::instance->globalUniformBuffer){ + setupShaderRenderPass(globalUniforms); + } else { // find list of used shaders shaders.clear(); for (auto & rqObj : renderQueue){ @@ -249,8 +252,6 @@ namespace sre { glUseProgram(shader->shaderProgramId); setupShaderRenderPass(shader); } - } else { - setupShaderRenderPass(globalUniforms); } } @@ -428,6 +429,4 @@ namespace sre { draw(mesh, transformation, material); } - - } diff --git a/src/sre/Shader.cpp b/src/sre/Shader.cpp index a7ddba94..d4ce9c09 100755 --- a/src/sre/Shader.cpp +++ b/src/sre/Shader.cpp @@ -759,15 +759,15 @@ namespace sre { glDeleteProgram( oldShaderProgramId ); // delete old shader if any } // setup global uniform - glUseProgram(shaderProgramId); - auto index = glGetUniformBlockIndex(shaderProgramId, "g_global_uniforms"); - if (index != GL_INVALID_INDEX){ - const int globalUniformBindingIndex = 1; - glUniformBlockBinding(shaderProgramId, index, globalUniformBindingIndex); - glBindBufferRange(GL_UNIFORM_BUFFER, globalUniformBindingIndex, - Renderer::instance->globalUniformBuffer, 0, Renderer::instance->globalUniformBufferSize); - } else { - + if (Renderer::instance->globalUniformBuffer){ + glUseProgram(shaderProgramId); + auto index = glGetUniformBlockIndex(shaderProgramId, "g_global_uniforms"); + if (index != GL_INVALID_INDEX){ + const int globalUniformBindingIndex = 1; + glUniformBlockBinding(shaderProgramId, index, globalUniformBindingIndex); + glBindBufferRange(GL_UNIFORM_BUFFER, globalUniformBindingIndex, + Renderer::instance->globalUniformBuffer, 0, Renderer::instance->globalUniformBufferSize); + } } updateUniformsAndAttributes(); From 08f6d967fd9306bf6de22443619fac0faede7c25 Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Sun, 18 Mar 2018 23:05:53 +0100 Subject: [PATCH 10/16] Add picojson notice --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 742a64ce..e2448e09 100644 --- a/README.md +++ b/README.md @@ -50,4 +50,5 @@ API documentation is defined in header files. * https://www.opengl.org/registry/ OpenGL Registry * https://github.com/ocornut/imgui ImGui 1.53 (bundled) * https://github.com/BalazsJako/ImGuiColorTextEdit ImGuiColorTextEdit (bundled) + * https://github.com/kazuho/picojson PicoJSON(bundled) From 653f53e9d72cd0cd76348e0719e5d9a4ed80dbb7 Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Wed, 21 Mar 2018 10:15:49 +0100 Subject: [PATCH 11/16] Flatten render queue. --- README.md | 2 +- include/sre/RenderPass.hpp | 3 +- src/sre/RenderPass.cpp | 69 +++++++++++++++++++------------------- version-history.md | 2 +- 4 files changed, 39 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index e2448e09..b9638a5c 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ sre provides: * Support for 2D or 3D rendering * GUI rendering (using Dear ImGui) * Emscripten support (allows cross compiling to HTML 5 + WebGL) - * VR support + * VR support (OpenVR) * Bump mapping To keep sre as simple and flexible as possible the following features are not a part of sre: diff --git a/include/sre/RenderPass.hpp b/include/sre/RenderPass.hpp index bb7d1d6b..f9f80bde 100755 --- a/include/sre/RenderPass.hpp +++ b/include/sre/RenderPass.hpp @@ -124,7 +124,8 @@ namespace sre { struct RenderQueueObj{ std::shared_ptr mesh; glm::mat4 modelTransform; - std::vector> materials; + std::shared_ptr material; + int subMesh = 0; }; struct GlobalUniforms{ glm::mat4* g_view; diff --git a/src/sre/RenderPass.cpp b/src/sre/RenderPass.cpp index 1748fbac..fc48d127 100755 --- a/src/sre/RenderPass.cpp +++ b/src/sre/RenderPass.cpp @@ -127,7 +127,7 @@ namespace sre { void RenderPass::draw(std::shared_ptr& meshPtr, glm::mat4 modelTransform, std::shared_ptr& material_ptr) { assert(!mIsFinished && "RenderPass is finished. Can no longer be modified."); - renderQueue.emplace_back(RenderQueueObj{meshPtr, modelTransform, {material_ptr}}); + renderQueue.emplace_back(RenderQueueObj{meshPtr, modelTransform, material_ptr}); } void RenderPass::setupShaderRenderPass(Shader *shader){ @@ -215,7 +215,7 @@ namespace sre { renderQueue.emplace_back(RenderQueueObj{ mesh, glm::mat4(1), - {material} + material }); } @@ -243,9 +243,7 @@ namespace sre { // find list of used shaders shaders.clear(); for (auto & rqObj : renderQueue){ - for (auto & mat : rqObj.materials){ - shaders.insert(mat->getShader().get()); - } + shaders.insert(rqObj.material->getShader().get()); } // update global uniforms for (auto shader : shaders){ @@ -348,37 +346,40 @@ namespace sre { std::vector> materials) { assert(!mIsFinished && "RenderPass is finished. Can no longer be modified."); assert(meshPtr->indices.size() == 0 || meshPtr->indices.size() == materials.size()); - renderQueue.emplace_back(RenderQueueObj{meshPtr, modelTransform, materials}); + int subMesh = 0; + for (auto & mat : materials){ + renderQueue.emplace_back(RenderQueueObj{meshPtr, modelTransform, mat,subMesh}); + subMesh++; + } } void RenderPass::drawInstance(RenderQueueObj& rqObj) { - for (int i=0;igetShader().get(); - assert(mesh != nullptr); - builder.renderStats->drawCalls++; - setupShader(rqObj.modelTransform, shader); - if (material != lastBoundMaterial) { - builder.renderStats->stateChangesMaterial++; - lastBoundMaterial = material; - lastBoundMeshId = -1; // force mesh to rebind - material->bind(); - } - if (mesh->meshId != lastBoundMeshId) { - builder.renderStats->stateChangesMesh++; - lastBoundMeshId = mesh->meshId; - mesh->bind(shader); - } - if (mesh->getIndexSets() == 0){ - glDrawArrays((GLenum) mesh->getMeshTopology(), 0, mesh->getVertexCount()); - } else { - auto offsetCount = mesh->elementBufferOffsetCount[i]; - GLsizei indexCount = offsetCount.second; - glDrawElements((GLenum) mesh->getMeshTopology(i), indexCount, GL_UNSIGNED_SHORT, BUFFER_OFFSET(offsetCount.first)); - } + auto material_ptr = rqObj.material; + Mesh* mesh = rqObj.mesh.get(); + auto material = material_ptr.get(); + auto shader = material->getShader().get(); + assert(mesh != nullptr); + builder.renderStats->drawCalls++; + setupShader(rqObj.modelTransform, shader); + if (material != lastBoundMaterial) { + builder.renderStats->stateChangesMaterial++; + lastBoundMaterial = material; + lastBoundMeshId = -1; // force mesh to rebind + material->bind(); + } + if (mesh->meshId != lastBoundMeshId) { + builder.renderStats->stateChangesMesh++; + lastBoundMeshId = mesh->meshId; + mesh->bind(shader); + } + if (mesh->getIndexSets() == 0){ + glDrawArrays((GLenum) mesh->getMeshTopology(), 0, mesh->getVertexCount()); + } else { + auto offsetCount = mesh->elementBufferOffsetCount[rqObj.subMesh]; + + GLsizei indexCount = offsetCount.second; + glDrawElements((GLenum) mesh->getMeshTopology(rqObj.subMesh), indexCount, GL_UNSIGNED_SHORT, BUFFER_OFFSET(offsetCount.first)); } } @@ -391,7 +392,7 @@ namespace sre { if (spriteBatch == nullptr) return; for (int i=0;imaterials.size();i++) { - renderQueue.emplace_back(RenderQueueObj{spriteBatch->spriteMeshes[i], modelTransform, {spriteBatch->materials[i]}}); + renderQueue.emplace_back(RenderQueueObj{spriteBatch->spriteMeshes[i], modelTransform, spriteBatch->materials[i]}); } } @@ -400,7 +401,7 @@ namespace sre { if (spriteBatch == nullptr) return; for (int i=0;imaterials.size();i++) { - renderQueue.emplace_back(RenderQueueObj{spriteBatch->spriteMeshes[i], modelTransform, {spriteBatch->materials[i]}}); + renderQueue.emplace_back(RenderQueueObj{spriteBatch->spriteMeshes[i], modelTransform, spriteBatch->materials[i]}); } } diff --git a/version-history.md b/version-history.md index 24df7249..d6e7ca68 100644 --- a/version-history.md +++ b/version-history.md @@ -1,5 +1,5 @@ ## Version history - + * 1.0.7 Performance improvements (global uniform buffer). Flatten render queue. * 1.0.6 Inspector: Correctly show integer attributes in Mesh and Shader. Inspector: Navigate mesh data (vertex attributes). Fix binding of integer attributes. Matrix arrays as uniforms. * 1.0.5 Improve indexed mesh performance. * 1.0.4 WebGL 2 support. Fix WebGL shader warnings. From f622da9240aaec3374128c12cf2aa689e6d2d610 Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Wed, 21 Mar 2018 10:22:42 +0100 Subject: [PATCH 12/16] Clean up code --- src/sre/Framebuffer.cpp | 4 +--- src/sre/RenderPass.cpp | 4 ++-- src/sre/WorldLights.cpp | 4 ++-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/sre/Framebuffer.cpp b/src/sre/Framebuffer.cpp index 22bba9b1..2de213ef 100644 --- a/src/sre/Framebuffer.cpp +++ b/src/sre/Framebuffer.cpp @@ -118,9 +118,7 @@ namespace sre{ glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObjectId); if (dirty){ for (int i=0;itextureId, 0); - } + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_TEXTURE_2D, textures[i]->textureId, 0); } if (depthTexture){ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture->textureId, 0); diff --git a/src/sre/RenderPass.cpp b/src/sre/RenderPass.cpp index fc48d127..0a5d1cd0 100755 --- a/src/sre/RenderPass.cpp +++ b/src/sre/RenderPass.cpp @@ -236,7 +236,7 @@ namespace sre { globalUniforms.g_lightPosType = reinterpret_cast(buffer.data() + g_lightPosTypeOffset ); return true; } (); - auto rinfo = renderInfo(); + auto& rinfo = renderInfo(); if (Renderer::instance->globalUniformBuffer){ setupShaderRenderPass(globalUniforms); } else { @@ -411,7 +411,7 @@ namespace sre { void RenderPass::blit(std::shared_ptr texture, glm::mat4 transformation) { auto material = Shader::getBlit()->createMaterial(); - material->setTexture(texture); + material->setTexture(std::move(texture)); blit(material, transformation); } diff --git a/src/sre/WorldLights.cpp b/src/sre/WorldLights.cpp index 838f8bad..e5ea3293 100755 --- a/src/sre/WorldLights.cpp +++ b/src/sre/WorldLights.cpp @@ -20,7 +20,7 @@ namespace sre { int WorldLights::addLight(const Light & light){ lights.push_back(light); - return lights.size()-1; + return (int)lights.size()-1; } void WorldLights::removeLight(int index){ @@ -36,7 +36,7 @@ namespace sre { } int WorldLights::lightCount(){ - return lights.size(); + return (int)lights.size(); } void WorldLights::setAmbientLight(const glm::vec3& ambientLight){ From 82de7e37c5d3ea49cd68504dd24b099c6f6993df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Nobel-J=C3=B8rgensen?= Date: Thu, 22 Mar 2018 14:49:23 +0100 Subject: [PATCH 13/16] VR: Fix left/right eye offset bug. --- src/sre/VR.cpp | 4 ++-- version-history.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sre/VR.cpp b/src/sre/VR.cpp index 732f4371..75ba9e1a 100644 --- a/src/sre/VR.cpp +++ b/src/sre/VR.cpp @@ -90,8 +90,8 @@ namespace sre if (m_rTrackedDevicePose[vr::k_unTrackedDeviceIndex_Hmd].bPoseIsValid) { m_mat4HMDPose = m_rmat4DevicePose[vr::k_unTrackedDeviceIndex_Hmd]; - left.setViewTransform(glm::inverse(mat4eyePosLeft*m_mat4HMDPose)*baseViewTransform); - right.setViewTransform(glm::inverse(mat4eyePosRight*m_mat4HMDPose)*baseViewTransform); + left.setViewTransform(glm::inverse(m_mat4HMDPose*mat4eyePosLeft)*baseViewTransform); + right.setViewTransform(glm::inverse(m_mat4HMDPose*mat4eyePosRight)*baseViewTransform); } #endif } diff --git a/version-history.md b/version-history.md index d6e7ca68..9e93db5b 100644 --- a/version-history.md +++ b/version-history.md @@ -1,5 +1,5 @@ ## Version history - * 1.0.7 Performance improvements (global uniform buffer). Flatten render queue. + * 1.0.7 Performance improvements (global uniform buffer). Flatten render queue. VR: Fix left/right eye offset bug. * 1.0.6 Inspector: Correctly show integer attributes in Mesh and Shader. Inspector: Navigate mesh data (vertex attributes). Fix binding of integer attributes. Matrix arrays as uniforms. * 1.0.5 Improve indexed mesh performance. * 1.0.4 WebGL 2 support. Fix WebGL shader warnings. From 2617e79d18b88d7b3432b5ac1c86eac20de32e03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Nobel-J=C3=B8rgensen?= Date: Thu, 22 Mar 2018 15:03:27 +0100 Subject: [PATCH 14/16] Fix windows compile warning --- include/sre/SpriteBatch.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/sre/SpriteBatch.hpp b/include/sre/SpriteBatch.hpp index e558b0b8..0749350a 100644 --- a/include/sre/SpriteBatch.hpp +++ b/include/sre/SpriteBatch.hpp @@ -5,8 +5,7 @@ * License: MIT */ -#pragma once - +#pragma once #include #include "sre/Sprite.hpp" #include "Mesh.hpp" @@ -58,9 +57,10 @@ class SpriteBatch { size ++; start ++; } - if (size >= std::numeric_limits::max()){ - LOG_ERROR("More than %i sprites in a batch ",std::numeric_limits::max()); - sprites.resize(std::numeric_limits::max()); + + if (size >= USHRT_MAX){ + LOG_ERROR("More than %i sprites in a batch ", USHRT_MAX); + sprites.resize(USHRT_MAX); return *this; } return *this; From 6104e54a7fc643e6397743eb7ba45268fa7000f9 Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Sat, 24 Mar 2018 10:36:01 +0100 Subject: [PATCH 15/16] Fix GLSL ES bug (removed precision) --- em-build.sh | 2 ++ include/sre/impl/ShaderSource.inl | 14 +++++++------- src/embedded_deps/global_uniforms_incl.glsl | 14 +++++++------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/em-build.sh b/em-build.sh index 82d3ae40..fe17bc2b 100755 --- a/em-build.sh +++ b/em-build.sh @@ -33,6 +33,7 @@ emcc -Iinclude src/imgui/imgui.cpp \ src/sre/SpriteAtlas.cpp \ src/sre/Inspector.cpp \ src/sre/Log.cpp \ + src/sre/impl/UniformSet.cpp \ test/$FILENAME.cpp \ -O2 -std=c++14 -s USE_WEBGL2=1 -s FORCE_FILESYSTEM=1 -s TOTAL_MEMORY=67108864 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS='["png"]' --preload-file test_data -s USE_SDL=2 -o html/$FILENAME.html done @@ -62,6 +63,7 @@ emcc -Iinclude src/imgui/imgui.cpp \ src/sre/SpriteAtlas.cpp \ src/sre/Inspector.cpp \ src/sre/Log.cpp \ + src/sre/impl/UniformSet.cpp \ examples/$FILENAME.cpp \ -O2 -std=c++14 -s USE_WEBGL2=1 -s FORCE_FILESYSTEM=1 -s TOTAL_MEMORY=33554432 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS='["png"]' --preload-file examples_data -s USE_SDL=2 -o html/$FILENAME.html done diff --git a/include/sre/impl/ShaderSource.inl b/include/sre/impl/ShaderSource.inl index f2edb90b..10e9d501 100644 --- a/include/sre/impl/ShaderSource.inl +++ b/include/sre/impl/ShaderSource.inl @@ -803,13 +803,13 @@ std::make_pair("global_uniforms_incl.glsl",R"(#if __VER layout(std140) uniform g_global_uniforms { #endif #ifdef GL_ES -uniform precision highp mat4 g_view; -uniform precision highp mat4 g_projection; -uniform precision highp vec4 g_viewport; -uniform precision highp vec4 g_cameraPos; -uniform precision highp vec4 g_ambientLight; -uniform precision highp vec4 g_lightColorRange[SI_LIGHTS]; -uniform precision highp vec4 g_lightPosType[SI_LIGHTS]; +uniform highp mat4 g_view; +uniform highp mat4 g_projection; +uniform highp vec4 g_viewport; +uniform highp vec4 g_cameraPos; +uniform highp vec4 g_ambientLight; +uniform highp vec4 g_lightColorRange[SI_LIGHTS]; +uniform highp vec4 g_lightPosType[SI_LIGHTS]; #else uniform mat4 g_view; uniform mat4 g_projection; diff --git a/src/embedded_deps/global_uniforms_incl.glsl b/src/embedded_deps/global_uniforms_incl.glsl index f7768bd5..1166697d 100644 --- a/src/embedded_deps/global_uniforms_incl.glsl +++ b/src/embedded_deps/global_uniforms_incl.glsl @@ -2,13 +2,13 @@ layout(std140) uniform g_global_uniforms { #endif #ifdef GL_ES -uniform precision highp mat4 g_view; -uniform precision highp mat4 g_projection; -uniform precision highp vec4 g_viewport; -uniform precision highp vec4 g_cameraPos; -uniform precision highp vec4 g_ambientLight; -uniform precision highp vec4 g_lightColorRange[SI_LIGHTS]; -uniform precision highp vec4 g_lightPosType[SI_LIGHTS]; +uniform highp mat4 g_view; +uniform highp mat4 g_projection; +uniform highp vec4 g_viewport; +uniform highp vec4 g_cameraPos; +uniform highp vec4 g_ambientLight; +uniform highp vec4 g_lightColorRange[SI_LIGHTS]; +uniform highp vec4 g_lightPosType[SI_LIGHTS]; #else uniform mat4 g_view; uniform mat4 g_projection; From d3f407a96c4a71b49ddcd08a8c5902be289ab29f Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Sat, 24 Mar 2018 11:04:14 +0100 Subject: [PATCH 16/16] Change benchmark 64k --- test/benchmark64k-heavy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/benchmark64k-heavy.cpp b/test/benchmark64k-heavy.cpp index abaf873b..839c537b 100644 --- a/test/benchmark64k-heavy.cpp +++ b/test/benchmark64k-heavy.cpp @@ -57,9 +57,9 @@ class Benchmark64KExample { for (int i = 0;isetTexture(Texture::create().withFile("examples_data/test.png").withGenerateMipmaps(true).build()); + materials[i]->setTexture(Texture::create().withFile("test_data/t_explosionsheet.png").withGenerateMipmaps(true).build()); } else { - materials[i]->setTexture(Texture::create().withFile("examples_data/cartman.png").withGenerateMipmaps(true).build()); + materials[i]->setTexture(Texture::create().withFile("test_data/gamma-test.png").withGenerateMipmaps(true).build()); } }