This commit is contained in:
milek7
2018-07-08 21:33:26 +02:00
parent 1c26096c5c
commit 13ba3fcd13
40 changed files with 917 additions and 506 deletions

View File

@@ -84,6 +84,8 @@ set(SOURCES
"gl/shader_mvp.cpp"
"gl/vao.cpp"
"gl/ubo.cpp"
"gl/framebuffer.cpp"
"gl/renderbuffer.cpp"
)
set (PREFIX "")

View File

@@ -349,12 +349,6 @@ global_settings::ConfigParse(cParser &Parser) {
>> shadowtune.depth
>> shadowtune.distance;
}
else if (token == "smoothtraction")
{
// podwójna jasność ambient
Parser.getTokens();
Parser >> bSmoothTraction;
}
else if( token == "splinefidelity" ) {
// segment size during spline->geometry conversion
float splinefidelity;
@@ -680,10 +674,6 @@ global_settings::ConfigParse(cParser &Parser) {
bEnableTraction = false; // false = pantograf się nie połamie
bLiveTraction = false; // false = pantografy zawsze zbierają 95% MaxVoltage
}
if (iMultisampling)
{ // antyaliasing całoekranowy wyłącza rozmywanie drutów
bSmoothTraction = false;
}
if (iMultiplayer > 0)
{
bInactivePause = false; // okno "w tle" nie może pauzować, jeśli włączona komunikacja

View File

@@ -105,7 +105,7 @@ struct global_settings {
bool bWireFrame{ false };
bool bAdjustScreenFreq{ true };
float BaseDrawRange{ 2500.f };
int DynamicLightCount{ 3 };
int DynamicLightCount{ 8 };
bool ScaleSpecularValues{ true };
bool BasicRenderer{ false };
bool RenderShadows{ true };
@@ -119,7 +119,6 @@ struct global_settings {
float FieldOfView{ 45.f }; // vertical field of view for the camera. TODO: move it to the renderer
GLint iMaxTextureSize{ 4096 }; // maksymalny rozmiar tekstury
int iMultisampling{ 2 }; // tryb antyaliasingu: 0=brak,1=2px,2=4px,3=8px,4=16px
bool bSmoothTraction{ true }; // wygładzanie drutów starym sposobem
float SplineFidelity{ 1.f }; // determines segment size during conversion of splines to geometry
bool ResourceSweep{ true }; // gfx resource garbage collection
bool ResourceMove{ false }; // gfx resources are moved between cpu and gpu side instead of sending a copy

View File

@@ -774,22 +774,13 @@ opengl_texture::flip_vertical() {
}
}
void
texture_manager::assign_units( GLint const Helper, GLint const Shadows, GLint const Normals, GLint const Diffuse ) {
m_units[ 0 ].unit = Helper;
m_units[ 1 ].unit = Shadows;
m_units[ 2 ].unit = Normals;
m_units[ 3 ].unit = Diffuse;
}
void
texture_manager::unit( GLint const Textureunit ) {
if( m_activeunit == Textureunit ) { return; }
m_activeunit = Textureunit;
::glActiveTexture( Textureunit );
::glActiveTexture( GL_TEXTURE0 + Textureunit );
}
// ustalenie numeru tekstury, wczytanie jeśli jeszcze takiej nie było
@@ -860,32 +851,32 @@ texture_manager::bind( std::size_t const Unit, texture_handle const Texture ) {
m_textures[ Texture ].second = m_garbagecollector.timestamp();
if( Texture == m_units[ Unit ].texture ) {
if( Texture == m_units[ Unit ] ) {
// don't bind again what's already active
return;
}
// TBD, TODO: do binding in texture object, add support for other types than 2d
if( m_units[ Unit ].unit == 0 ) { return; }
unit( m_units[ Unit ].unit );
unit(Unit);
if( Texture != null_handle ) {
#ifndef EU07_DEFERRED_TEXTURE_UPLOAD
// NOTE: we could bind dedicated 'error' texture here if the id isn't valid
::glBindTexture( GL_TEXTURE_2D, texture(Texture).id );
m_units[ Unit ].texture = Texture;
m_units[ Unit ] = Texture;
#else
if( true == texture( Texture ).bind() ) {
m_units[ Unit ].texture = Texture;
m_units[ Unit ] = Texture;
}
else {
// TODO: bind a special 'error' texture on failure
::glBindTexture( GL_TEXTURE_2D, 0 );
m_units[ Unit ].texture = 0;
m_units[ Unit ] = 0;
}
#endif
}
else {
::glBindTexture( GL_TEXTURE_2D, 0 );
m_units[ Unit ].texture = 0;
m_units[ Unit ] = 0;
}
// all done
return;
@@ -909,7 +900,7 @@ texture_manager::update() {
if( m_garbagecollector.sweep() > 0 ) {
for( auto &unit : m_units ) {
unit.texture = -1;
unit = -1;
}
}
}

View File

@@ -81,8 +81,6 @@ public:
texture_manager();
~texture_manager() { delete_textures(); }
void
assign_units( GLint const Helper, GLint const Shadows, GLint const Normals, GLint const Diffuse );
// activates specified texture unit
void
unit( GLint const Textureunit );
@@ -112,11 +110,6 @@ private:
typedef std::unordered_map<std::string, std::size_t> index_map;
struct texture_unit {
GLint unit { 0 };
texture_handle texture { null_handle }; // current (most recently bound) texture
};
// methods:
// checks whether specified texture is in the texture bank. returns texture id, or npos.
texture_handle
@@ -132,7 +125,7 @@ private:
texturetimepointpair_sequence m_textures;
index_map m_texturemappings;
garbage_collector<texturetimepointpair_sequence> m_garbagecollector { m_textures, 600, 60, "texture" };
std::array<texture_unit, 4> m_units;
std::array<texture_handle, 4> m_units;
GLint m_activeunit { 0 };
};

View File

@@ -1361,7 +1361,7 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
}
if( ( Bank == 0 ) && ( false == Geometry2.empty() ) ) {
// special variant, replace existing data for a turntable track
GfxRenderer.Replace( vertices, Geometry2[ 0 ] );
GfxRenderer.Replace( vertices, Geometry2[ 0 ], GL_TRIANGLE_STRIP );
}
}
if (m_material1)
@@ -1377,10 +1377,10 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
if( ( Bank == 0 ) && ( false == Geometry1.empty() ) ) {
// special variant, replace existing data for a turntable track
Segment->RenderLoft( vertices, m_origin, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength );
GfxRenderer.Replace( vertices, Geometry1[ 0 ] );
GfxRenderer.Replace( vertices, Geometry1[ 0 ], GL_TRIANGLE_STRIP );
vertices.clear(); // reuse the scratchpad
Segment->RenderLoft( vertices, m_origin, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength );
GfxRenderer.Replace( vertices, Geometry1[ 1 ] );
GfxRenderer.Replace( vertices, Geometry1[ 1 ], GL_TRIANGLE_STRIP );
}
}
break;
@@ -2478,13 +2478,13 @@ TTrack * TTrack::RaAnimate()
if( m_material1 ) {
// left blade
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts3, -nnumPts, fTexLength, 1.0, 0, bladelength, SwitchExtension->fOffset2 );
GfxRenderer.Replace( vertices, Geometry1[ 2 ] );
GfxRenderer.Replace( vertices, Geometry1[ 2 ], GL_TRIANGLE_STRIP );
vertices.clear();
}
if( m_material2 ) {
// right blade
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts4, -nnumPts, fTexLength, 1.0, 0, bladelength, -fMaxOffset + SwitchExtension->fOffset1 );
GfxRenderer.Replace( vertices, Geometry2[ 2 ] );
GfxRenderer.Replace( vertices, Geometry2[ 2 ], GL_TRIANGLE_STRIP );
vertices.clear();
}
}
@@ -2492,13 +2492,13 @@ TTrack * TTrack::RaAnimate()
if( m_material1 ) {
// right blade
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts4, -nnumPts, fTexLength, 1.0, 0, bladelength, -SwitchExtension->fOffset2 );
GfxRenderer.Replace( vertices, Geometry1[ 2 ] );
GfxRenderer.Replace( vertices, Geometry1[ 2 ], GL_TRIANGLE_STRIP );
vertices.clear();
}
if( m_material2 ) {
// left blade
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts3, -nnumPts, fTexLength, 1.0, 0, bladelength, fMaxOffset - SwitchExtension->fOffset1 );
GfxRenderer.Replace( vertices, Geometry2[ 2 ] );
GfxRenderer.Replace( vertices, Geometry2[ 2 ], GL_TRIANGLE_STRIP );
vertices.clear();
}
}

View File

@@ -566,37 +566,21 @@ TTraction::wire_color() const {
switch( PowerState ) {
case 1: {
// czerwone z podłączonym zasilaniem 1
// color.r = 1.0f;
// color.g = 0.0f;
// color.b = 0.0f;
// cyan
color = glm::vec3 { 0.f, 174.f / 255.f, 239.f / 255.f };
break;
}
case 2: {
// zielone z podłączonym zasilaniem 2
// color.r = 0.0f;
// color.g = 1.0f;
// color.b = 0.0f;
// yellow
color = glm::vec3 { 240.f / 255.f, 228.f / 255.f, 0.f };
break;
}
case 3: {
//żółte z podłączonym zasilaniem z obu stron
// color.r = 1.0f;
// color.g = 1.0f;
// color.b = 0.0f;
// green
color = glm::vec3 { 0.f, 239.f / 255.f, 118.f / 255.f };
break;
}
case 4: {
// niebieskie z podłączonym zasilaniem
// color.r = 0.5f;
// color.g = 0.5f;
// color.b = 1.0f;
// white for powered, red for ends
color = (
psPowered != nullptr ?
@@ -611,46 +595,6 @@ TTraction::wire_color() const {
color.g *= 0.6f;
color.b *= 0.6f;
}
/*
switch( iTries ) {
case 0: {
color = glm::vec3{ 239.f / 255.f, 128.f / 255.f, 128.f / 255.f }; // red
break;
}
case 1: {
color = glm::vec3{ 240.f / 255.f, 228.f / 255.f, 0.f }; // yellow
break;
}
case 5: {
color = glm::vec3{ 0.f / 255.f, 239.f / 255.f, 118.f / 255.f }; // green
break;
}
default: {
color = glm::vec3{ 239.f / 255.f, 239.f / 255.f, 239.f / 255.f };
break;
}
}
*/
/*
switch( iLast ) {
case 0: {
color = glm::vec3{ 240.f / 255.f, 228.f / 255.f, 0.f }; // yellow
break;
}
case 1: {
color = glm::vec3{ 239.f / 255.f, 128.f / 255.f, 128.f / 255.f }; // red
break;
}
case 2: {
color = glm::vec3{ 0.f / 255.f, 239.f / 255.f, 118.f / 255.f }; // green
break;
}
default: {
color = glm::vec3{ 239.f / 255.f, 239.f / 255.f, 239.f / 255.f };
break;
}
}
*/
}
return color;
}

View File

@@ -16,7 +16,7 @@ namespace gl
active = this;
T::bind(*static_cast<T*>(active));
}
void unbind()
static void unbind()
{
active = nullptr;
T::bind(0);

0
gl/framebuffer.cpp Normal file
View File

0
gl/framebuffer.h Normal file
View File

58
gl/glsl_common.h Normal file
View File

@@ -0,0 +1,58 @@
#include "ubo.h"
namespace gl
{
const std::string glsl_common =
"const uint MAX_LIGHTS = " + std::to_string(MAX_LIGHTS) + "U;\n" +
"const uint MAX_PARAMS = " + std::to_string(MAX_PARAMS) + "U;\n" +
R"STRING(
const uint LIGHT_SPOT = 0U;
const uint LIGHT_POINT = 1U;
const uint LIGHT_DIR = 2U;
struct light_s
{
vec3 pos;
uint type;
vec3 dir;
float in_cutoff;
vec3 color;
float out_cutoff;
float linear;
float quadratic;
};
layout(std140) uniform light_ubo
{
vec3 ambient;
float fog_density;
vec3 fog_color;
uint lights_count;
light_s lights[MAX_LIGHTS];
};
layout (std140) uniform model_ubo
{
mat4 modelview;
mat3 modelviewnormal;
vec4 param[MAX_PARAMS];
vec3 velocity;
float opacity;
float emission;
};
layout (std140) uniform scene_ubo
{
mat4 projection;
mat4 lightview;
float time;
};
)STRING";
}

0
gl/renderbuffer.cpp Normal file
View File

0
gl/renderbuffer.h Normal file
View File

View File

@@ -3,6 +3,7 @@
#include <fstream>
#include <sstream>
#include "shader.h"
#include "glsl_common.h"
inline bool strcend(std::string const &value, std::string const &ending)
{
@@ -11,17 +12,51 @@ inline bool strcend(std::string const &value, std::string const &ending)
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
}
gl::shader::shader(const std::string &filename)
std::string gl::shader::read_file(const std::string &filename)
{
std::stringstream stream;
std::ifstream f;
f.exceptions(std::ifstream::badbit);
f.open(filename);
f.open("shaders/" + filename);
stream << f.rdbuf();
f.close();
std::string str = stream.str();
return str;
}
void gl::shader::expand_includes(std::string &str)
{
size_t start_pos = 0;
std::string magic = "#include";
while ((start_pos = str.find(magic, start_pos)) != str.npos)
{
size_t fp = str.find('<', start_pos);
size_t fe = str.find('>', start_pos);
if (fp == str.npos || fe == str.npos)
return;
std::string filename = str.substr(fp + 1, fe - fp - 1);
std::string content;
if (filename != "common")
content = read_file(filename);
else
content = glsl_common;
str.replace(start_pos, fe - start_pos + 1, content);
}
}
gl::shader::shader(const std::string &filename)
{
std::string str = read_file(filename);
expand_includes(str);
std::cout << (str) << std::endl;;
const GLchar *cstr = str.c_str();
if (!cstr[0])
@@ -58,7 +93,19 @@ gl::shader::~shader()
void gl::program::init()
{
bind();
glUniform1i(glGetUniformLocation(*this, "tex"), 3);
int i = 0;
GLuint loc;
while (true)
{
std::string name = "tex" + std::to_string(i + 1);
loc = glGetUniformLocation(*this, name.c_str());
if (loc != -1)
glUniform1i(loc, i);
else
break;
i++;
}
}
gl::program::program()

View File

@@ -14,6 +14,10 @@ namespace gl
public:
shader(const std::string &filename);
~shader();
private:
void expand_includes(std::string &str);
std::string read_file(const std::string &filename);
};
class program : public object, public bindable<program>

View File

@@ -3,6 +3,14 @@
void gl::program_mvp::init()
{
glUniformBlockBinding(*this, 0, glGetUniformBlockIndex(*this, "scene_ubo"));
glUniformBlockBinding(*this, 1, glGetUniformBlockIndex(*this, "model_ubo"));
GLuint index;
if ((index = glGetUniformBlockIndex(*this, "scene_ubo")) != GL_INVALID_INDEX)
glUniformBlockBinding(*this, 0, index);
if ((index = glGetUniformBlockIndex(*this, "model_ubo")) != GL_INVALID_INDEX)
glUniformBlockBinding(*this, 1, index);
if ((index = glGetUniformBlockIndex(*this, "light_ubo")) != GL_INVALID_INDEX)
glUniformBlockBinding(*this, 2, index);
}

View File

@@ -2,7 +2,6 @@
#include "bindable.h"
#define UBS_PAD(x) uint64_t : x * 4; uint64_t : x * 4;
#define DEFINE_UBS(x, y) _Pragma("pack(push, 1)"); struct x y; _Pragma("pack(pop)")
namespace gl
{
@@ -20,29 +19,82 @@ namespace gl
void update(void *data, int offset, int size);
};
// layout std140
// structs must match with GLSL
// ordered to minimize padding
_Pragma("pack(push, 1)")
struct scene_ubs
{
glm::mat4 projection;
void set(const glm::mat4 &m)
{
projection = m;
}
glm::mat4 lightview;
float time;
};
static_assert(sizeof(scene_ubs) == 132, "bad size of ubs");
const size_t MAX_PARAMS = 3;
struct model_ubs
{
glm::mat4 modelview;
glm::mat4 modelviewnormal;
glm::mat3x4 modelviewnormal;
glm::vec4 param[MAX_PARAMS];
void set(const glm::mat4 &m)
glm::vec3 velocity;
float opacity;
float emission;
void set_modelview(const glm::mat4 &mv)
{
modelview = m;
modelviewnormal = glm::mat3(glm::transpose(glm::inverse(m)));
modelview = mv;
modelviewnormal = glm::mat3(glm::transpose(glm::inverse(mv)));
}
};
static_assert(sizeof(model_ubs) == 156 + 8 * MAX_PARAMS, "bad size of ubs");
struct light_element_ubs
{
enum type_e
{
SPOT = 0,
POINT,
DIR
};
glm::vec3 pos;
type_e type;
glm::vec3 dir;
float in_cutoff;
glm::vec3 color;
float out_cutoff;
float linear;
float quadratic;
UBS_PAD(8);
};
static_assert(sizeof(light_element_ubs) == 64, "bad size of ubs");
const size_t MAX_LIGHTS = 16;
struct light_ubs
{
glm::vec3 ambient;
float fog_density;
glm::vec3 fog_color;
uint32_t lights_count;
light_element_ubs lights[MAX_LIGHTS];
};
static_assert(sizeof(light_ubs) == 32 + sizeof(light_element_ubs) * MAX_LIGHTS, "bad size of ubs");
_Pragma("pack(pop)")
}

189
lua_ffi.h
View File

@@ -1,93 +1,96 @@
const char lua_ffi[] = "local ffi = require(\"ffi\")\n"
"ffi.cdef[[\n"
"struct memcell_values { const char *str; double num1; double num2; };\n"
"\n"
"typedef struct TEvent TEvent;\n"
"typedef struct TTrack TTrack;\n"
"typedef struct TIsolated TIsolated;\n"
"typedef struct TDynamicObject TDynamicObject;\n"
"typedef struct TMemCell TMemCell;\n"
"typedef struct memcell_values memcell_values;\n"
"\n"
"TEvent* scriptapi_event_create(const char* name, double delay, double randomdelay, void (*handler)(TEvent*, TDynamicObject*));\n"
"TEvent* scriptapi_event_find(const char* name);\n"
"const char* scriptapi_event_getname(TEvent *e);\n"
"void scriptapi_event_dispatch(TEvent *e, TDynamicObject *activator, double delay);\n"
"\n"
"TTrack* scriptapi_track_find(const char* name);\n"
"bool scriptapi_track_isoccupied(TTrack *track);\n"
"\n"
"TIsolated* scriptapi_isolated_find(const char* name);\n"
"bool scriptapi_isolated_isoccupied(TIsolated *isolated);\n"
"\n"
"const char* scriptapi_train_getname(TDynamicObject *dyn);\n"
"void scriptapi_dynobj_putvalues(TDynamicObject *dyn, const char *str, double num1, double num2);\n"
"\n"
"TMemCell* scriptapi_memcell_find(const char *name);\n"
"memcell_values scriptapi_memcell_read(TMemCell *mc);\n"
"void scriptapi_memcell_update(TMemCell *mc, const char *str, double num1, double num2);\n"
"\n"
"double scriptapi_random(double a, double b);\n"
"void scriptapi_writelog(const char* txt);\n"
"void scriptapi_writeerrorlog(const char* txt);\n"
"]]\n"
"\n"
"local ns = ffi.C\n"
"\n"
"local module = {}\n"
"\n"
"module.event_create = ns.scriptapi_event_create\n"
"function module.event_preparefunc(f)\n"
" return ffi.cast(\"void (*)(TEvent*, TDynamicObject*)\", f)\n"
"end\n"
"module.event_find = ns.scriptapi_event_find\n"
"function module.event_getname(a)\n"
" return ffi.string(ns.scriptapi_event_getname(a))\n"
"end\n"
"module.event_dispatch = ns.scriptapi_event_dispatch\n"
"function module.event_dispatch_n(a, b, c)\n"
" ns.scriptapi_event_dispatch(ns.scriptapi_event_find(a), b, c)\n"
"end\n"
"\n"
"module.track_find = ns.scriptapi_track_find\n"
"module.track_isoccupied = ns.scriptapi_track_isoccupied\n"
"function module.track_isoccupied_n(a)\n"
" return ns.scriptapi_track_isoccupied(ns.scriptapi_track_find(a))\n"
"end\n"
"\n"
"module.isolated_find = ns.scriptapi_isolated_find\n"
"module.isolated_isoccupied = ns.scriptapi_isolated_isoccupied\n"
"function module.isolated_isoccupied_n(a)\n"
" return ns.scriptapi_isolated_isoccupied(ns.scriptapi_isolated_find(a))\n"
"end\n"
"\n"
"function module.train_getname(a)\n"
" return ffi.string(ns.scriptapi_train_getname(a))\n"
"end\n"
"function module.dynobj_putvalues(a, b)\n"
" ns.scriptapi_dynobj_putvalues(a, b.str, b.num1, b.num2)\n"
"end\n"
"\n"
"module.memcell_find = ns.scriptapi_memcell_find\n"
"function module.memcell_read(a)\n"
" native = ns.scriptapi_memcell_read(a)\n"
" mc = { }\n"
" mc.str = ffi.string(native.str)\n"
" mc.num1 = native.num1\n"
" mc.num2 = native.num2\n"
" return mc\n"
"end\n"
"function module.memcell_read_n(a)\n"
" return module.memcell_read(ns.scriptapi_memcell_find(a))\n"
"end\n"
"function module.memcell_update(a, b)\n"
" ns.scriptapi_memcell_update(a, b.str, b.num1, b.num2)\n"
"end\n"
"function module.memcell_update_n(a, b)\n"
" ns.scriptapi_memcell_update(ns.scriptapi_memcell_find(a), b.str, b.num1, b.num2)\n"
"end\n"
"\n"
"module.random = ns.scriptapi_random\n"
"module.writelog = ns.scriptapi_writelog\n"
"module.writeerrorlog = ns.scriptapi_writeerrorlog\n"
"\nreturn module\n";
const char lua_ffi[] = R"STRING(
local ffi = require("ffi")
ffi.cdef[[
struct memcell_values { const char *str; double num1; double num2; };
typedef struct TEvent TEvent;
typedef struct TTrack TTrack;
typedef struct TIsolated TIsolated;
typedef struct TDynamicObject TDynamicObject;
typedef struct TMemCell TMemCell;
typedef struct memcell_values memcell_values;
TEvent* scriptapi_event_create(const char* name, double delay, double randomdelay, void (*handler)(TEvent*, TDynamicObject*));
TEvent* scriptapi_event_find(const char* name);
const char* scriptapi_event_getname(TEvent *e);
void scriptapi_event_dispatch(TEvent *e, TDynamicObject *activator, double delay);
TTrack* scriptapi_track_find(const char* name);
bool scriptapi_track_isoccupied(TTrack *track);
TIsolated* scriptapi_isolated_find(const char* name);
bool scriptapi_isolated_isoccupied(TIsolated *isolated);
const char* scriptapi_train_getname(TDynamicObject *dyn);
void scriptapi_dynobj_putvalues(TDynamicObject *dyn, const char *str, double num1, double num2);
TMemCell* scriptapi_memcell_find(const char *name);
memcell_values scriptapi_memcell_read(TMemCell *mc);
void scriptapi_memcell_update(TMemCell *mc, const char *str, double num1, double num2);
double scriptapi_random(double a, double b);
void scriptapi_writelog(const char* txt);
void scriptapi_writeerrorlog(const char* txt);
]]
local ns = ffi.C
local module = {}
module.event_create = ns.scriptapi_event_create
function module.event_preparefunc(f)
return ffi.cast("void (*)(TEvent*, TDynamicObject*)", f)
end
module.event_find = ns.scriptapi_event_find
function module.event_getname(a)
return ffi.string(ns.scriptapi_event_getname(a))
end
module.event_dispatch = ns.scriptapi_event_dispatch
function module.event_dispatch_n(a, b, c)
ns.scriptapi_event_dispatch(ns.scriptapi_event_find(a), b, c)
end
module.track_find = ns.scriptapi_track_find
module.track_isoccupied = ns.scriptapi_track_isoccupied
function module.track_isoccupied_n(a)
return ns.scriptapi_track_isoccupied(ns.scriptapi_track_find(a))
end
module.isolated_find = ns.scriptapi_isolated_find
module.isolated_isoccupied = ns.scriptapi_isolated_isoccupied
function module.isolated_isoccupied_n(a)
return ns.scriptapi_isolated_isoccupied(ns.scriptapi_isolated_find(a))
end
function module.train_getname(a)
return ffi.string(ns.scriptapi_train_getname(a))
end
function module.dynobj_putvalues(a, b)
ns.scriptapi_dynobj_putvalues(a, b.str, b.num1, b.num2)
end
module.memcell_find = ns.scriptapi_memcell_find
function module.memcell_read(a)
native = ns.scriptapi_memcell_read(a)
mc = { }
mc.str = ffi.string(native.str)
mc.num1 = native.num1
mc.num2 = native.num2
return mc
end
function module.memcell_read_n(a)
return module.memcell_read(ns.scriptapi_memcell_find(a))
end
function module.memcell_update(a, b)
ns.scriptapi_memcell_update(a, b.str, b.num1, b.num2)
end
function module.memcell_update_n(a, b)
ns.scriptapi_memcell_update(ns.scriptapi_memcell_find(a), b.str, b.num1, b.num2)
end
module.random = ns.scriptapi_random
module.writelog = ns.scriptapi_writelog
module.writeerrorlog = ns.scriptapi_writeerrorlog
return module;
)STRING";

View File

@@ -22,11 +22,6 @@ opengl_material::deserialize( cParser &Input, bool const Loadnow ) {
result = true; // once would suffice but, eh
}
has_alpha = (
texture1 != null_handle ?
GfxRenderer.Texture( texture1 ).has_alpha :
false );
return result;
}
@@ -34,7 +29,7 @@ opengl_material::deserialize( cParser &Input, bool const Loadnow ) {
bool
opengl_material::deserialize_mapping( cParser &Input, int const Priority, bool const Loadnow ) {
// token can be a key or block end
std::string const key { Input.getToken<std::string>( true, "\n\r\t ,;[]" ) };
std::string key = Input.getToken<std::string>( true, "\n\r\t ,;[]" );
if( ( true == key.empty() ) || ( key == "}" ) ) { return false; }
@@ -55,21 +50,28 @@ opengl_material::deserialize_mapping( cParser &Input, int const Priority, bool c
; // all work is done in the header
}
}
else if( key == "texture1:" ) {
if( ( texture1 == null_handle )
|| ( Priority > priority1 ) ) {
else if (key.compare(0, 7, "texture") == 0) {
key.erase(0, 7);
size_t num = std::stoi(key) - 1;
if (num < textures.size() &&
(textures[num] == null_handle || Priority > m_priority[num]))
{
std::replace(value.begin(), value.end(), '\\', '/');
texture1 = GfxRenderer.Fetch_Texture( value, Loadnow );
priority1 = Priority;
textures[num] = GfxRenderer.Fetch_Texture( value, Loadnow );
m_priority[num] = Priority;
}
}
else if( key == "texture2:" ) {
if( ( texture2 == null_handle )
|| ( Priority > priority2 ) ) {
std::replace(value.begin(), value.end(), '\\', '/');
texture2 = GfxRenderer.Fetch_Texture( value, Loadnow );
priority2 = Priority;
}
else if (key == "shader:" &&
(!shader || Priority > m_priority[max_textures]))
{
shader = GfxRenderer.Fetch_Shader(value);
m_priority[max_textures] = Priority;
}
else if (key == "opacity:" &&
Priority > m_priority[max_textures + 1])
{
opacity = std::stoi(value); //m7t: handle exception
m_priority[max_textures + 1] = Priority;
}
else if( value == "{" ) {
// unrecognized or ignored token, but comes with attribute block and potential further nesting
@@ -129,16 +131,26 @@ material_manager::create( std::string const &Filename, bool const Loadnow ) {
}
else {
// if there's no .mat file, this could be legacy method of referring just to diffuse texture directly, make a material out of it in such case
material.texture1 = GfxRenderer.Fetch_Texture( Filename, Loadnow );
if( material.texture1 == null_handle ) {
material.textures[0] = GfxRenderer.Fetch_Texture( Filename, Loadnow );
if( material.textures[0] == null_handle ) {
// if there's also no texture, give up
return null_handle;
}
// use texture path and name to tell the newly created materials apart
filename = GfxRenderer.Texture( material.texture1 ).name;
filename = GfxRenderer.Texture( material.textures[0] ).name;
erase_extension( filename );
material.name = filename;
material.has_alpha = GfxRenderer.Texture( material.texture1 ).has_alpha;
}
if (!material.shader)
material.shader = GfxRenderer.Fetch_Shader("default");
if (std::isnan(material.opacity))
{
if (material.textures[0] != null_handle)
material.opacity = GfxRenderer.Texture( material.textures[0] ).has_alpha ? 0.0f : 1.0f;
else
material.opacity = 1.0f;
}
material_handle handle = m_materials.size();

View File

@@ -11,18 +11,22 @@ http://mozilla.org/MPL/2.0/.
#include "Classes.h"
#include "Texture.h"
#include "gl/shader.h"
typedef int material_handle;
// a collection of parameters for the rendering setup.
// for modern opengl this translates to set of attributes for the active shaders,
// for legacy opengl this is basically just texture(s) assigned to geometry
// for modern opengl this translates to set of attributes for shaders
struct opengl_material {
static const size_t max_textures = 2;
texture_handle texture1 { null_handle }; // primary texture, typically diffuse+apha
texture_handle texture2 { null_handle }; // secondary texture, typically normal+reflection
// primary texture, typically diffuse+apha
// secondary texture, typically normal+reflection
std::array<texture_handle, max_textures> textures = { null_handle };
std::shared_ptr<gl::program> shader;
float opacity = std::numeric_limits<float>::quiet_NaN();
bool has_alpha { false }; // alpha state, calculated from presence of alpha in texture1
std::string name;
// constructors
@@ -39,8 +43,8 @@ private:
deserialize_mapping( cParser &Input, int const Priority, bool const Loadnow );
// members
int priority1 { -1 }; // priority of last loaded primary texture
int priority2 { -1 }; // priority of last loaded secondary texture
// priorities for textures, shader, opacity
std::array<int, max_textures + 2> m_priority = { -1 };
};
class material_manager {

View File

@@ -46,6 +46,104 @@ basic_vertex::deserialize( std::istream &s ) {
texture.y = sn_utils::ld_float32( s );
}
// based on
// Lengyel, Eric. “Computing Tangent Space Basis Vectors for an Arbitrary Mesh”.
// Terathon Software, 2001. http://terathon.com/code/tangent.html
void calculate_tangent(vertex_array &vertices, int type)
{
size_t vertex_count = vertices.size();
if (!vertex_count || vertices[0].tangent.w != 0.0f)
return;
size_t triangle_count;
if (type == GL_TRIANGLES)
triangle_count = vertex_count / 3;
else if (type == GL_TRIANGLE_STRIP)
triangle_count = vertex_count - 2;
else if (type == GL_TRIANGLE_FAN)
triangle_count = vertex_count - 2;
else
return;
std::vector<glm::vec3> tan(vertex_count * 2);
for (size_t a = 0; a < triangle_count; a++)
{
size_t i1, i2, i3;
if (type == GL_TRIANGLES)
{
i1 = a * 3;
i2 = a * 3 + 1;
i3 = a * 3 + 2;
}
else if (type == GL_TRIANGLE_STRIP)
{
if (a % 2 == 0)
{
i1 = a;
i2 = a + 1;
}
else
{
i1 = a + 1;
i2 = a;
}
i3 = a + 2;
}
else if (type == GL_TRIANGLE_FAN)
{
i1 = 0;
i2 = a + 1;
i3 = a + 2;
}
const glm::vec3 &v1 = vertices[i1].position;
const glm::vec3 &v2 = vertices[i2].position;
const glm::vec3 &v3 = vertices[i3].position;
const glm::vec2 &w1 = vertices[i1].texture;
const glm::vec2 &w2 = vertices[i2].texture;
const glm::vec2 &w3 = vertices[i3].texture;
float x1 = v2.x - v1.x;
float x2 = v3.x - v1.x;
float y1 = v2.y - v1.y;
float y2 = v3.y - v1.y;
float z1 = v2.z - v1.z;
float z2 = v3.z - v1.z;
float s1 = w2.x - w1.x;
float s2 = w3.x - w1.x;
float t1 = w2.y - w1.y;
float t2 = w3.y - w1.y;
float r = 1.0F / (s1 * t2 - s2 * t1);
glm::vec3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
(t2 * z1 - t1 * z2) * r);
glm::vec3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
(s1 * z2 - s2 * z1) * r);
tan[i1] += sdir;
tan[i2] += sdir;
tan[i3] += sdir;
tan[vertex_count + i1] += tdir;
tan[vertex_count + i2] += tdir;
tan[vertex_count + i3] += tdir;
}
for (size_t a = 0; a < vertex_count; a++)
{
const glm::vec3 &n = vertices[a].normal;
const glm::vec3 &t = tan[a];
const glm::vec3 &t2 = tan[vertex_count + a];
vertices[a].tangent = glm::vec4(glm::normalize((t - n * glm::dot(n, t))),
(glm::dot(glm::cross(n, t), t2) < 0.0F) ? -1.0F : 1.0F);
}
}
// generic geometry bank class, allows storage, update and drawing of geometry chunks
// creates a new geometry chunk of specified type from supplied vertex data. returns: handle to the chunk
@@ -100,9 +198,9 @@ geometry_bank::append( gfx::vertex_array &Vertices, gfx::geometry_handle const &
// draws geometry stored in specified chunk
void
geometry_bank::draw( gfx::geometry_handle const &Geometry, unsigned int const Streams ) {
geometry_bank::draw( gfx::geometry_handle const &Geometry ) {
// template method implementation
draw_( Geometry, Streams );
draw_( Geometry );
}
// frees subclass-specific resources associated with the bank, typically called when the bank wasn't in use for a period of time
@@ -145,7 +243,7 @@ opengl_vbogeometrybank::replace_( gfx::geometry_handle const &Geometry ) {
// draw() subclass details
void
opengl_vbogeometrybank::draw_( gfx::geometry_handle const &Geometry, unsigned int const Streams ) {
opengl_vbogeometrybank::draw_( gfx::geometry_handle const &Geometry) {
if( m_buffer == 0 ) {
// if there's no buffer, we'll have to make one
@@ -193,17 +291,11 @@ opengl_vbogeometrybank::draw_( gfx::geometry_handle const &Geometry, unsigned in
m_vao = std::make_unique<gl::vao>();
glBindBuffer( GL_ARRAY_BUFFER, m_buffer );
if( Streams & gfx::stream::position )
m_vao->setup_attrib(0, 3, GL_FLOAT, sizeof(basic_vertex), 0 * sizeof(GL_FLOAT));
// NOTE: normal and color streams share the data, making them effectively mutually exclusive
if( Streams & gfx::stream::normal )
m_vao->setup_attrib(1, 3, GL_FLOAT, sizeof(basic_vertex), 3 * sizeof(GL_FLOAT));
else if( Streams & gfx::stream::color )
m_vao->setup_attrib(1, 3, GL_FLOAT, sizeof(basic_vertex), 3 * sizeof(GL_FLOAT));
if( Streams & gfx::stream::texture )
m_vao->setup_attrib(2, 2, GL_FLOAT, sizeof(basic_vertex), 6 * sizeof(GL_FLOAT));
m_vao->setup_attrib(0, 3, GL_FLOAT, sizeof(basic_vertex), 0 * sizeof(GL_FLOAT));
// NOTE: normal and color streams share the data
m_vao->setup_attrib(1, 3, GL_FLOAT, sizeof(basic_vertex), 3 * sizeof(GL_FLOAT));
m_vao->setup_attrib(2, 2, GL_FLOAT, sizeof(basic_vertex), 6 * sizeof(GL_FLOAT));
m_vao->setup_attrib(3, 4, GL_FLOAT, sizeof(basic_vertex), 8 * sizeof(GL_FLOAT));
glBindBuffer(GL_ARRAY_BUFFER, 0);
m_vao->unbind();
@@ -271,7 +363,6 @@ geometrybank_manager::create_bank() {
// creates a new geometry chunk of specified type from supplied vertex data, in specified bank. returns: handle to the chunk or NULL
gfx::geometry_handle
geometrybank_manager::create_chunk( gfx::vertex_array const &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) {
auto const newchunkhandle = bank( Geometry ).first->create( Vertices, Type );
if( newchunkhandle.chunk != 0 ) { return { Geometry.bank, newchunkhandle.chunk }; }
@@ -293,14 +384,14 @@ geometrybank_manager::append( gfx::vertex_array &Vertices, gfx::geometry_handle
}
// draws geometry stored in specified chunk
void
geometrybank_manager::draw( gfx::geometry_handle const &Geometry, unsigned int const Streams ) {
geometrybank_manager::draw( gfx::geometry_handle const &Geometry ) {
if( Geometry == null_handle ) { return; }
auto &bankrecord = bank( Geometry );
bankrecord.second = m_garbagecollector.timestamp();
bankrecord.first->draw( Geometry, Streams );
bankrecord.first->draw( Geometry );
}
// provides direct access to vertex data of specfied chunk

View File

@@ -26,6 +26,7 @@ struct basic_vertex {
glm::vec3 position; // 3d space
glm::vec3 normal; // 3d space
glm::vec2 texture; // uv space
glm::vec4 tangent; // xyz - tangent, w - handedness
basic_vertex() = default;
basic_vertex( glm::vec3 Position, glm::vec3 Normal, glm::vec2 Texture ) :
@@ -35,19 +36,10 @@ struct basic_vertex {
void deserialize( std::istream& );
};
// data streams carried in a vertex
enum stream {
none = 0x0,
position = 0x1,
normal = 0x2,
color = 0x4, // currently normal and colour streams are stored in the same slot, and mutually exclusive
texture = 0x8
};
unsigned int const basic_streams { stream::position | stream::normal | stream::texture };
unsigned int const color_streams { stream::position | stream::color | stream::texture };
typedef std::vector<basic_vertex> vertex_array;
void calculate_tangent(vertex_array &vertices, int type);
// generic geometry bank class, allows storage, update and drawing of geometry chunks
struct geometry_handle {
@@ -100,11 +92,11 @@ public:
append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry );
// draws geometry stored in specified chunk
void
draw( gfx::geometry_handle const &Geometry, unsigned int const Streams = basic_streams );
draw( gfx::geometry_handle const &Geometry );
// draws geometry stored in supplied list of chunks
template <typename Iterator_>
void
draw( Iterator_ First, Iterator_ Last, unsigned int const Streams = basic_streams ) { while( First != Last ) { draw( *First, Streams ); ++First; } }
draw( Iterator_ First, Iterator_ Last ) { while( First != Last ) { draw( *First ); ++First; } }
// frees subclass-specific resources associated with the bank, typically called when the bank wasn't in use for a period of time
void
release();
@@ -146,7 +138,7 @@ private:
// replace() subclass details
virtual void replace_( gfx::geometry_handle const &Geometry ) = 0;
// draw() subclass details
virtual void draw_( gfx::geometry_handle const &Geometry, unsigned int const Streams ) = 0;
virtual void draw_( gfx::geometry_handle const &Geometry ) = 0;
// resource release subclass details
virtual void release_() = 0;
};
@@ -185,7 +177,7 @@ private:
replace_( gfx::geometry_handle const &Geometry );
// draw() subclass details
void
draw_( gfx::geometry_handle const &Geometry, unsigned int const Streams );
draw_( gfx::geometry_handle const &Geometry );
// release() subclass details
void
release_();
@@ -224,12 +216,12 @@ public:
append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry );
// draws geometry stored in specified chunk
void
draw( gfx::geometry_handle const &Geometry, unsigned int const Streams = basic_streams );
draw( gfx::geometry_handle const &Geometry);
template <typename Iterator_>
void
draw( Iterator_ First, Iterator_ Last, unsigned int const Streams = basic_streams ) {
draw( Iterator_ First, Iterator_ Last ) {
while( First != Last ) {
draw( *First, Streams );
draw( *First );
++First; } }
// provides direct access to vertex data of specfied chunk
gfx::vertex_array const &

View File

@@ -27,12 +27,11 @@ int const EU07_ENVIRONMENTBUFFERSIZE { 256 }; // size of (square) environmental
void
opengl_light::apply_intensity( float const Factor ) {
// m7t setup light ubo here
factor = Factor;
}
void
opengl_light::apply_angle() {
// m7t setup light ubo here
}
void
@@ -100,18 +99,11 @@ opengl_renderer::Init( GLFWwindow *Window ) {
glFrontFace( GL_CCW );
glEnable( GL_CULL_FACE );
m_textures.assign_units( m_helpertextureunit, m_shadowtextureunit, m_normaltextureunit, m_diffusetextureunit ); // TODO: add reflections unit
UILayer.set_unit( m_diffusetextureunit );
select_unit( m_diffusetextureunit );
glDepthFunc( GL_LEQUAL );
glEnable( GL_DEPTH_TEST );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_BLEND );
glLineWidth( 1.0f );
glPointSize( 3.0f );
if( true == Global.ScaleSpecularValues ) {
m_specularopaquescalefactor = 0.25f;
m_speculartranslucentscalefactor = 1.5f;
@@ -132,8 +124,6 @@ opengl_renderer::Init( GLFWwindow *Window ) {
light.is_directional = false;
//m7t config light ubo here
m_lights.emplace_back( light );
}
// preload some common textures
@@ -141,9 +131,6 @@ opengl_renderer::Init( GLFWwindow *Window ) {
m_glaretexture = Fetch_Texture( "fx/lightglare" );
m_suntexture = Fetch_Texture( "fx/sun" );
m_moontexture = Fetch_Texture( "fx/moon" );
if( m_helpertextureunit >= 0 ) {
m_reflectiontexture = Fetch_Texture( "fx/reflections" );
}
WriteLog( "...gfx data pre-loading done" );
// prepare basic geometry chunks
@@ -157,13 +144,30 @@ opengl_renderer::Init( GLFWwindow *Window ) {
{ { size, -size, 0.f }, glm::vec3(), { 0.f, 0.f } } },
geometrybank, GL_TRIANGLE_STRIP );
gl::shader vert("shaders/simple.vert");
gl::shader frag("shaders/simple.frag");
shader = std::make_unique<gl::program_mvp>(std::vector<std::reference_wrapper<const gl::shader>>({vert, frag}));
shader->init();
m_vertex_shader = std::make_unique<gl::shader>("simple.vert");
scene_ubo = std::make_unique<gl::ubo>(sizeof(gl::scene_ubs), 0);
model_ubo = std::make_unique<gl::ubo>(sizeof(gl::model_ubs), 1);
light_ubo = std::make_unique<gl::ubo>(sizeof(gl::light_ubs), 2);
memset(&light_ubs, 0, sizeof(light_ubs));
// m7t: tbd: plug into material system?
{
gl::shader vert("traction.vert");
gl::shader frag("traction.frag");
gl::program *prog = new gl::program_mvp({vert, frag});
prog->init();
m_line_shader = std::unique_ptr<gl::program>(prog);
}
{
gl::shader vert("freespot.vert");
gl::shader frag("freespot.frag");
gl::program *prog = new gl::program_mvp({vert, frag});
prog->init();
m_freespot_shader = std::unique_ptr<gl::program>(prog);
}
m_invalid_material = Fetch_Material("invalid");
return true;
}
@@ -268,17 +272,21 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
setup_matrices();
// render
setup_drawing( true );
setup_units( true, false, false );
glDebug("render environment");
scene_ubs.time = Timer::GetTime();
scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION);
scene_ubo->update(&scene_ubs, 0, sizeof(scene_ubs));
Render( &World.Environment );
scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION);
scene_ubo->update(&scene_ubs, 0, sizeof(scene_ubs));
// opaque parts...
setup_drawing( false );
setup_units( true, true, true );
shader->bind();
if( false == FreeFlyModeFlag ) {
glDebug("render cab opaque");
switch_units( true, true, false );
setup_shadow_map( m_cabshadowtexture, m_cabshadowtexturematrix );
// cache shadow colour in case we need to account for cab light
auto const shadowcolor { m_shadowcolor };
@@ -293,7 +301,6 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
}
glDebug("render opaque region");
switch_units( true, true, true );
setup_shadow_map( m_shadowtexture, m_shadowtexturematrix );
Render( simulation::Region );
@@ -304,7 +311,6 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
if( false == FreeFlyModeFlag ) {
glDebug("render translucent cab");
// cab render is performed without shadows, due to low resolution and number of models without windows :|
switch_units( true, true, false );
setup_shadow_map( m_cabshadowtexture, m_cabshadowtexturematrix );
// cache shadow colour in case we need to account for cab light
auto const shadowcolor{ m_shadowcolor };
@@ -318,8 +324,7 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
}
}
shader->unbind();
/*
if( m_environmentcubetexturesupport ) {
// restore default texture matrix for reflections cube map
select_unit( m_helpertextureunit );
@@ -328,6 +333,7 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
select_unit( m_diffusetextureunit );
::glMatrixMode( GL_MODELVIEW );
}
*/
glDebug("color pass done");
}
@@ -438,6 +444,7 @@ opengl_renderer::setup_matrices() {
::glMatrixMode( GL_PROJECTION );
OpenGLMatrices.load_matrix( m_renderpass.camera.projection() );
/*
if( ( m_renderpass.draw_mode == rendermode::color )
&& ( m_environmentcubetexturesupport ) ) {
// special case, for colour render pass setup texture matrix for reflections cube map
@@ -447,6 +454,7 @@ opengl_renderer::setup_matrices() {
::glMultMatrixf( glm::value_ptr( glm::inverse( glm::mat4{ glm::mat3{ m_renderpass.camera.modelview() } } ) ) );
select_unit( m_diffusetextureunit );
}
*/
// trim modelview matrix just to rotation, since rendering is done in camera-centric world space
::glMatrixMode( GL_MODELVIEW );
@@ -484,42 +492,12 @@ opengl_renderer::setup_drawing( bool const Alpha ) {
}
}
// configures, enables and disables specified texture units
void
opengl_renderer::setup_units( bool const Diffuse, bool const Shadows, bool const Reflections ) {
// diffuse texture unit.
// NOTE: diffuse texture mapping is never fully disabled, alpha channel information is always included
select_unit( m_diffusetextureunit );
// update unit state
m_unitstate.diffuse = Diffuse;
m_unitstate.shadows = Shadows;
m_unitstate.reflections = Reflections;
}
// configures shadow texture unit for specified shadow map and conersion matrix
void
opengl_renderer::setup_shadow_map( GLuint const Texture, glm::mat4 const &Transformation ) {
}
// enables and disables specified texture units
void
opengl_renderer::switch_units( bool const Diffuse, bool const Shadows, bool const Reflections ) {
// diffuse texture unit.
// NOTE: toggle actually disables diffuse texture mapping, unlike setup counterpart
if( true == Diffuse ) {
select_unit( m_diffusetextureunit );
}
else {
select_unit( m_diffusetextureunit );
}
// update unit state
m_unitstate.diffuse = Diffuse;
m_unitstate.shadows = Shadows;
m_unitstate.reflections = Reflections;
}
void
opengl_renderer::setup_shadow_color( glm::vec4 const &Shadowcolor ) {
}
@@ -577,10 +555,7 @@ opengl_renderer::Render( world_environment *Environment ) {
::glDepthMask( GL_FALSE );
::glPushMatrix();
scene_ubs.set(OpenGLMatrices.data(GL_PROJECTION));
model_ubs.set(OpenGLMatrices.data(GL_MODELVIEW));
scene_ubo->update(&scene_ubs, 0, sizeof(scene_ubs));
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
model_ubo->update(&model_ubs, 0, sizeof(model_ubs));
// skydome
@@ -590,12 +565,9 @@ opengl_renderer::Render( world_environment *Environment ) {
//m7t: restore celestial bodies
shader->bind();
// clouds
if( Environment->m_clouds.mdCloud ) {
// setup
Disable_Lights();
//m7t set cloud color
// render
Render( Environment->m_clouds.mdCloud, nullptr, 100.0 );
@@ -624,20 +596,23 @@ opengl_renderer::Create_Bank() {
// creates a new geometry chunk of specified type from supplied vertex data, in specified bank. returns: handle to the chunk or NULL
gfx::geometry_handle
opengl_renderer::Insert( gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) {
gfx::calculate_tangent(Vertices, Type);
return m_geometry.create_chunk( Vertices, Geometry, Type );
}
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
bool
opengl_renderer::Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, std::size_t const Offset ) {
opengl_renderer::Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type, std::size_t const Offset ) {
gfx::calculate_tangent(Vertices, Type);
return m_geometry.replace( Vertices, Geometry, Offset );
}
// adds supplied vertex data at the end of specified chunk
bool
opengl_renderer::Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry ) {
opengl_renderer::Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type ) {
gfx::calculate_tangent(Vertices, Type);
return m_geometry.append( Vertices, Geometry );
}
@@ -656,14 +631,40 @@ opengl_renderer::Fetch_Material( std::string const &Filename, bool const Loadnow
return m_materials.create( Filename, Loadnow );
}
std::shared_ptr<gl::program>
opengl_renderer::Fetch_Shader(const std::string &name)
{
auto it = m_shaders.find(name);
if (it == m_shaders.end())
{
gl::shader fragment("mat_" + name + ".frag");
gl::program *program = new gl::program_mvp({ fragment, *m_vertex_shader.get() });
program->init();
m_shaders.insert({name, std::shared_ptr<gl::program>(program)});
}
return m_shaders[name];
}
void
opengl_renderer::Bind_Material( material_handle const Material ) {
auto const &material = m_materials.material( Material );
if( false == Global.BasicRenderer ) {
m_textures.bind( textureunit::normals, material.texture2 );
if (Material != null_handle)
{
auto &material = m_materials.material( Material );
material.shader->bind();
size_t unit = 0;
for (auto &tex : material.textures)
{
if (tex == null_handle)
break;
m_textures.bind(unit, tex);
unit++;
}
}
m_textures.bind( textureunit::diffuse, material.texture1 );
else if (Material != m_invalid_material)
Bind_Material(m_invalid_material);
}
opengl_material const &
@@ -672,13 +673,6 @@ opengl_renderer::Material( material_handle const Material ) const {
return m_materials.material( Material );
}
// texture methods
void
opengl_renderer::select_unit( GLint const Textureunit ) {
return m_textures.unit( Textureunit );
}
texture_handle
opengl_renderer::Fetch_Texture( std::string const &Filename, bool const Loadnow ) {
@@ -688,7 +682,7 @@ opengl_renderer::Fetch_Texture( std::string const &Filename, bool const Loadnow
void
opengl_renderer::Bind_Texture( texture_handle const Texture ) {
m_textures.bind( textureunit::diffuse, Texture );
m_textures.bind( 0, Texture );
}
opengl_texture const &
@@ -937,10 +931,7 @@ opengl_renderer::Render( scene::shape_node const &Shape, bool const Ignorerange
}
}
// render
scene_ubs.set(OpenGLMatrices.data(GL_PROJECTION));
model_ubs.set(OpenGLMatrices.data(GL_MODELVIEW));
scene_ubo->update(&scene_ubs, 0, sizeof(scene_ubs));
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
model_ubo->update(&model_ubs, 0, sizeof(model_ubs));
m_geometry.draw( data.geometry );
@@ -994,6 +985,7 @@ opengl_renderer::Render( TAnimModel *Instance ) {
bool
opengl_renderer::Render( TDynamicObject *Dynamic ) {
glDebug("Render TDynamicObject");
Dynamic->renderme = m_renderpass.camera.visible( Dynamic );
if( false == Dynamic->renderme ) {
@@ -1206,6 +1198,7 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, float c
void
opengl_renderer::Render( TSubModel *Submodel ) {
glDebug("Render TSubModel");
if( ( Submodel->iVisible )
&& ( TSubModel::fSquareDist >= Submodel->fSquareMinDist )
@@ -1260,17 +1253,15 @@ opengl_renderer::Render( TSubModel *Submodel ) {
// specular strength in legacy models is set uniformly to 150, 150, 150 so we scale it down for opaque elements
}
model_ubs.emission = 0;
// ...luminance
auto const unitstate = m_unitstate;
if( Global.fLuminance < Submodel->fLight ) {
// zeby swiecilo na kolorowo
model_ubs.emission = Submodel->f4Emision.a;
}
// main draw call
scene_ubs.set(OpenGLMatrices.data(GL_PROJECTION));
model_ubs.set(OpenGLMatrices.data(GL_MODELVIEW));
scene_ubo->update(&scene_ubs, 0, sizeof(scene_ubs));
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
model_ubo->update(&model_ubs, 0, sizeof(model_ubs));
m_geometry.draw( Submodel->m_geometry );
@@ -1328,7 +1319,6 @@ opengl_renderer::Render( TSubModel *Submodel ) {
if( lightlevel > 0.f ) {
// material configuration:
Bind_Material( null_handle );
::glEnable( GL_BLEND );
::glPushMatrix();
@@ -1337,15 +1327,16 @@ opengl_renderer::Render( TSubModel *Submodel ) {
/*
setup_shadow_color( colors::white );
*/
auto const unitstate = m_unitstate;
switch_units( m_unitstate.diffuse, false, false );
glPointSize( std::max( 3.f, 5.f * distancefactor * anglefactor ) * 2.0f );
// main draw call
scene_ubs.set(OpenGLMatrices.data(GL_PROJECTION));
model_ubs.set(OpenGLMatrices.data(GL_MODELVIEW));
scene_ubo->update(&scene_ubs, 0, sizeof(scene_ubs));
model_ubs.param[0] = glm::vec4(glm::vec3(Submodel->f4Diffuse), 0.0f);
model_ubs.param[1] = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
model_ubs.emission = lightlevel * anglefactor;
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
model_ubo->update(&model_ubs, 0, sizeof(model_ubs));
model_ubs.emission = 0.0f;
m_freespot_shader->bind();
m_geometry.draw( Submodel->m_geometry );
@@ -1354,7 +1345,6 @@ opengl_renderer::Render( TSubModel *Submodel ) {
/*
setup_shadow_color( m_shadowcolor );
*/
switch_units( unitstate.diffuse, unitstate.shadows, unitstate.reflections );
::glPopMatrix();
}
@@ -1377,13 +1367,10 @@ opengl_renderer::Render( TSubModel *Submodel ) {
Bind_Material( null_handle );
// main draw call
scene_ubs.set(OpenGLMatrices.data(GL_PROJECTION));
model_ubs.set(OpenGLMatrices.data(GL_MODELVIEW));
scene_ubo->update(&scene_ubs, 0, sizeof(scene_ubs));
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
model_ubo->update(&model_ubs, 0, sizeof(model_ubs));
m_geometry.draw( Submodel->m_geometry, gfx::color_streams );
//m_geometry.draw( Submodel->m_geometry, gfx::color_streams );
}
break;
}
@@ -1422,10 +1409,7 @@ opengl_renderer::Render( TTrack *Track ) {
++m_debugstats.paths;
++m_debugstats.drawcalls;
scene_ubs.set(OpenGLMatrices.data(GL_PROJECTION));
model_ubs.set(OpenGLMatrices.data(GL_MODELVIEW));
scene_ubo->update(&scene_ubs, 0, sizeof(scene_ubs));
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
model_ubo->update(&model_ubs, 0, sizeof(model_ubs));
switch( m_renderpass.draw_mode ) {
@@ -1473,10 +1457,7 @@ opengl_renderer::Render( scene::basic_cell::path_sequence::const_iterator First,
}
}
scene_ubs.set(OpenGLMatrices.data(GL_PROJECTION));
model_ubs.set(OpenGLMatrices.data(GL_MODELVIEW));
scene_ubo->update(&scene_ubs, 0, sizeof(scene_ubs));
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
model_ubo->update(&model_ubs, 0, sizeof(model_ubs));
// first pass, material 1
@@ -1665,19 +1646,11 @@ opengl_renderer::Render_Alpha( cell_sequence::reverse_iterator First, cell_seque
::glPushMatrix();
auto const originoffset { cell->m_area.center - m_renderpass.camera.position() };
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
if( !Global.bSmoothTraction ) {
// na liniach kiepsko wygląda - robi gradient
::glDisable( GL_LINE_SMOOTH );
}
Bind_Material( null_handle );
// render
for( auto *traction : cell->m_traction ) { Render_Alpha( traction ); }
for( auto &lines : cell->m_lines ) { Render_Alpha( lines ); }
// post-render cleanup
::glLineWidth( 1.0 );
if( !Global.bSmoothTraction ) {
::glEnable( GL_LINE_SMOOTH );
}
::glPopMatrix();
}
@@ -1720,6 +1693,7 @@ opengl_renderer::Render_Alpha( TAnimModel *Instance ) {
void
opengl_renderer::Render_Alpha( TTraction *Traction ) {
glDebug("Render_Alpha TTraction");
double distancesquared;
switch( m_renderpass.draw_mode ) {
@@ -1743,31 +1717,26 @@ opengl_renderer::Render_Alpha( TTraction *Traction ) {
return;
}
// setup
/*
float const linealpha = static_cast<float>(
std::min(
1.25,
5000 * Traction->WireThickness / ( distancesquared + 1.0 ) ) ); // zbyt grube nie są dobre
::glLineWidth( linealpha );
*/
auto const distance { static_cast<float>( std::sqrt( distancesquared ) ) };
auto const linealpha {
20.f * Traction->WireThickness
/ std::max(
0.5f * Traction->radius() + 1.f,
distance - ( 0.5f * Traction->radius() ) ) };
::glLineWidth(
clamp(
0.5f * linealpha + Traction->WireThickness * Traction->radius() / 1000.f,
1.f, 1.5f ) );
if (m_widelines_supported)
glLineWidth(clamp(
0.5f * linealpha + Traction->WireThickness * Traction->radius() / 1000.f,
1.f, 1.5f ) );
// McZapkie-261102: kolor zalezy od materialu i zasniedzenia
// render
scene_ubs.set(OpenGLMatrices.data(GL_PROJECTION));
model_ubs.set(OpenGLMatrices.data(GL_MODELVIEW));
scene_ubo->update(&scene_ubs, 0, sizeof(scene_ubs));
model_ubs.param[0] = glm::vec4(Traction->wire_color(), linealpha);
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
model_ubo->update(&model_ubs, 0, sizeof(model_ubs));
m_geometry.draw( Traction->m_geometry );
m_line_shader->bind();
m_geometry.draw(Traction->m_geometry);
// debug data
++m_debugstats.traction;
++m_debugstats.drawcalls;
@@ -1775,6 +1744,7 @@ opengl_renderer::Render_Alpha( TTraction *Traction ) {
void
opengl_renderer::Render_Alpha( scene::lines_node const &Lines ) {
glDebug("Render_Alpha scene::lines_node");
auto const &data { Lines.data() };
@@ -1799,17 +1769,18 @@ opengl_renderer::Render_Alpha( scene::lines_node const &Lines ) {
0.5f * data.area.radius + 1.f,
distance - ( 0.5f * data.area.radius ) ) :
1.f ); // negative width means the lines are always opague
::glLineWidth(
clamp(
0.5f * linealpha + data.line_width * data.area.radius / 1000.f,
1.f, 8.f ) );
// render
scene_ubs.set(OpenGLMatrices.data(GL_PROJECTION));
model_ubs.set(OpenGLMatrices.data(GL_MODELVIEW));
if (m_widelines_supported)
glLineWidth(clamp(
0.5f * linealpha + data.line_width * data.area.radius / 1000.f,
1.f, 8.f ) );
scene_ubo->update(&scene_ubs, 0, sizeof(scene_ubs));
model_ubs.param[0] = glm::vec4(glm::vec3(data.lighting.diffuse * m_sunlight.ambient), linealpha);
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
model_ubo->update(&model_ubs, 0, sizeof(model_ubs));
m_geometry.draw( data.geometry );
m_line_shader->bind();
m_geometry.draw( data.geometry);
++m_debugstats.lines;
++m_debugstats.drawcalls;
}
@@ -1975,21 +1946,16 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
Bind_Material( Submodel->ReplacableSkinId[ -Submodel->m_material ] );
}
else {
// również 0
Bind_Material( Submodel->m_material );
}
// ...colors...
// m7t set material
// ...luminance
auto const unitstate = m_unitstate;
if( Global.fLuminance < Submodel->fLight ) {
}
// main draw call
scene_ubs.set(OpenGLMatrices.data(GL_PROJECTION));
model_ubs.set(OpenGLMatrices.data(GL_MODELVIEW));
scene_ubo->update(&scene_ubs, 0, sizeof(scene_ubs));
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
model_ubo->update(&model_ubs, 0, sizeof(model_ubs));
m_geometry.draw( Submodel->m_geometry );
@@ -2041,6 +2007,7 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
// reduce the glare in bright daylight
glarelevel = clamp( glarelevel - static_cast<float>(Global.fLuminance), 0.f, 1.f );
/*
if( glarelevel > 0.0f ) {
Bind_Texture( m_glaretexture );
::glDepthMask( GL_FALSE );
@@ -2055,15 +2022,13 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
switch_units( unitstate.diffuse, false, false );
// main draw call
scene_ubs.set(OpenGLMatrices.data(GL_PROJECTION));
model_ubs.set(OpenGLMatrices.data(GL_MODELVIEW));
scene_ubo->update(&scene_ubs, 0, sizeof(scene_ubs));
model_ubo->update(&model_ubs, 0, sizeof(model_ubs));
m_geometry.draw( m_billboardgeometry );
::glPopMatrix();
}
*/
}
}
}
@@ -2214,6 +2179,8 @@ opengl_renderer::info_stats() const {
void
opengl_renderer::Update_Lights( light_array &Lights ) {
glDebug("Update_Lights");
// arrange the light array from closest to farthest from current position of the camera
auto const camera = m_renderpass.camera.position();
std::sort(
@@ -2230,6 +2197,9 @@ opengl_renderer::Update_Lights( light_array &Lights ) {
if( count == 0 ) { return; }
auto renderlight = m_lights.begin();
size_t light_i = 1;
glm::mat4 mv = OpenGLMatrices.data(GL_MODELVIEW);
for( auto const &scenelight : Lights.data ) {
@@ -2266,26 +2236,30 @@ opengl_renderer::Update_Lights( light_array &Lights ) {
glm::max( glm::vec3{ colors::none }, scenelight.color * glm::vec3{ scenelight.intensity } - glm::vec3{ luminance } ),
renderlight->ambient[ 3 ] };
//m7t fill light
renderlight->apply_intensity();
renderlight->apply_angle();
gl::light_element_ubs *l = &light_ubs.lights[light_i];
l->pos = mv * glm::vec4(renderlight->position, 1.0f);
l->dir = mv * glm::vec4(renderlight->direction, 0.0f);
l->type = gl::light_element_ubs::SPOT;
l->in_cutoff = 0.906f;
l->out_cutoff = 0.866f;
l->color = renderlight->diffuse * renderlight->factor;
l->linear = 0.007f;
l->quadratic = 0.0002f;
light_i++;
++renderlight;
}
while( renderlight != m_lights.end() ) {
// if we went through all scene lights and there's still opengl lights remaining, kill these
++renderlight;
}
}
light_ubs.ambient = m_sunlight.ambient * m_sunlight.factor;
light_ubs.lights[0].type = gl::light_element_ubs::DIR;
light_ubs.lights[0].dir = mv * glm::vec4(m_sunlight.direction, 0.0f);
light_ubs.lights[0].color = m_sunlight.diffuse * m_sunlight.factor;
light_ubs.lights_count = light_i;
void
opengl_renderer::Disable_Lights() {
for( size_t idx = 0; idx < m_lights.size() + 1; ++idx ) {
}
light_ubo->update(&light_ubs, 0, sizeof(light_ubs));
}
bool
@@ -2330,40 +2304,19 @@ opengl_renderer::Init_caps() {
m_shadowbuffersize = std::min( m_shadowbuffersize, texturesize );
WriteLog( "Shadows map size capped at " + std::to_string( m_shadowbuffersize ) + " pixels" );
}
// cap the number of supported lights based on hardware
{
GLint maxlights;
::glGetIntegerv( GL_MAX_LIGHTS, &maxlights );
Global.DynamicLightCount = std::min( Global.DynamicLightCount, maxlights - 1 );
WriteLog( "Dynamic light amount capped at " + std::to_string( Global.DynamicLightCount ) + " (" + std::to_string(maxlights) + " lights total supported by the gfx card)" );
}
// select renderer mode
if( true == Global.BasicRenderer ) {
WriteLog( "Basic renderer selected, shadow and reflection mapping will be disabled" );
Global.RenderShadows = false;
m_diffusetextureunit = GL_TEXTURE0;
m_helpertextureunit = -1;
m_shadowtextureunit = -1;
m_normaltextureunit = -1;
}
else {
GLint maxtextureunits;
::glGetIntegerv( GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxtextureunits );
if( maxtextureunits < 4 ) {
WriteLog( "Less than 4 texture units, shadow and reflection mapping will be disabled" );
Global.BasicRenderer = true;
Global.RenderShadows = false;
m_diffusetextureunit = GL_TEXTURE0;
m_helpertextureunit = -1;
m_shadowtextureunit = -1;
m_normaltextureunit = -1;
}
}
Global.DynamicLightCount = std::min(Global.DynamicLightCount, 8);
if( Global.iMultisampling ) {
WriteLog( "Using multisampling x" + std::to_string( 1 << Global.iMultisampling ) );
}
glGetError();
glLineWidth(2.0f);
if (!glGetError())
m_widelines_supported = true;
else
WriteLog("warning: wide lines not supported");
return true;
}

View File

@@ -32,6 +32,8 @@ struct opengl_light : public basic_light {
GLuint id { (GLuint)-1 };
float factor;
void
apply_intensity( float const Factor = 1.0f );
void
@@ -138,10 +140,10 @@ public:
Insert( gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type );
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
bool
Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, std::size_t const Offset = 0 );
Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type, std::size_t const Offset = 0 );
// adds supplied vertex data at the end of specified chunk
bool
Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry );
Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type );
// provides direct access to vertex data of specfied chunk
gfx::vertex_array const &
Vertices( gfx::geometry_handle const &Geometry ) const;
@@ -150,6 +152,10 @@ public:
Fetch_Material( std::string const &Filename, bool const Loadnow = true );
void
Bind_Material( material_handle const Material );
// shader methods
std::shared_ptr<gl::program> Fetch_Shader(std::string const &name);
opengl_material const &
Material( material_handle const Material ) const;
// texture methods
@@ -159,9 +165,6 @@ public:
Bind_Texture( texture_handle const Texture );
opengl_texture const &
Texture( texture_handle const Texture ) const;
// light methods
void
Disable_Lights();
// utility methods
TSubModel const *
Pick_Control() const { return m_pickcontrolitem; }
@@ -196,13 +199,6 @@ private:
pickscenery
};
enum textureunit {
helper = 0,
shadows,
normals,
diffuse
};
struct debug_stats {
int dynamics { 0 };
int models { 0 };
@@ -225,13 +221,6 @@ private:
float draw_range { 0.0f };
};
struct units_state {
bool diffuse { false };
bool shadows { false };
bool reflections { false };
};
typedef std::vector<opengl_light> opengllight_array;
// methods
@@ -243,19 +232,12 @@ private:
setup_matrices();
void
setup_drawing( bool const Alpha = false );
void
setup_units( bool const Diffuse, bool const Shadows, bool const Reflections );
void
setup_shadow_map( GLuint const Texture, glm::mat4 const &Transformation );
void
setup_shadow_color( glm::vec4 const &Shadowcolor );
void
setup_environment_light( TEnvironmentType const Environment = e_flat );
void
switch_units( bool const Diffuse, bool const Shadows, bool const Reflections );
// helper, texture manager method; activates specified texture unit
void
select_unit( GLint const Textureunit );
// runs jobs needed to generate graphics for specified render pass
void
Render_pass( rendermode const Mode );
@@ -362,12 +344,6 @@ private:
int m_environmentupdatetime { 0 }; // time of the most recent environment map update
glm::dvec3 m_environmentupdatelocation; // coordinates of most recent environment map update
int m_helpertextureunit { GL_TEXTURE0 };
int m_shadowtextureunit { GL_TEXTURE1 };
int m_normaltextureunit { GL_TEXTURE2 };
int m_diffusetextureunit{ GL_TEXTURE3 };
units_state m_unitstate;
unsigned int m_framestamp; // id of currently rendered gfx frame
float m_framerate;
double m_updateaccumulator { 0.0 };
@@ -398,11 +374,23 @@ private:
GLuint m_gltimequery = 0;
GLuint64 m_gllasttime = 0;
std::unique_ptr<gl::program_mvp> shader;
std::unique_ptr<gl::shader> m_vertex_shader;
std::unique_ptr<gl::ubo> scene_ubo;
std::unique_ptr<gl::ubo> model_ubo;
std::unique_ptr<gl::ubo> light_ubo;
gl::scene_ubs scene_ubs;
gl::model_ubs model_ubs;
gl::light_ubs light_ubs;
std::unordered_map<std::string, std::shared_ptr<gl::program>> m_shaders;
std::unique_ptr<gl::program> m_line_shader;
std::unique_ptr<gl::program> m_freespot_shader;
material_handle m_invalid_material;
bool m_widelines_supported;
};
extern opengl_renderer GfxRenderer;

View File

@@ -194,7 +194,7 @@ shape_node::import( cParser &Input, scene::node_data const &Nodedata ) {
// TBT, TODO: add methods to material manager to access these simpler
auto const texturehandle = (
m_data.material != null_handle ?
GfxRenderer.Material( m_data.material ).texture1 :
GfxRenderer.Material( m_data.material ).textures[0] :
null_handle );
auto const &texture = (
texturehandle ?
@@ -340,7 +340,7 @@ shape_node::convert( TSubModel const *Submodel ) {
m_data.lighting.diffuse = Submodel->f4Diffuse;
m_data.lighting.specular = Submodel->f4Specular;
m_data.material = Submodel->m_material;
m_data.translucent = ( true == GfxRenderer.Material( m_data.material ).has_alpha );
m_data.translucent = ( true == GfxRenderer.Material( m_data.material ).opacity < 1.0f );
// NOTE: we set unlimited view range typical for terrain, because we don't expect to convert any other 3d models
m_data.rangesquared_max = std::numeric_limits<double>::max();

View File

@@ -2,6 +2,8 @@
in vec3 f_color;
#include <common>
void main()
{
gl_FragColor = vec4(f_color, 1.0f);

13
shaders/freespot.frag Normal file
View File

@@ -0,0 +1,13 @@
#version 330
#include <common>
void main()
{
float x = (gl_PointCoord.x - 0.5f) * 2.0f;
float y = (gl_PointCoord.y - 0.5f) * 2.0f;
float dist2 = abs(x * x + y * y);
if (dist2 > 0.5f * 0.5f)
discard;
gl_FragColor = param[0] * emission;
}

12
shaders/freespot.vert Normal file
View File

@@ -0,0 +1,12 @@
#version 330
in vec3 v_vert;
in vec3 v_normal;
in vec2 v_coord;
#include <common>
void main()
{
gl_Position = (projection * modelview) * vec4(v_vert, 1.0f);
}

83
shaders/mat_default.frag Normal file
View File

@@ -0,0 +1,83 @@
#version 330
in vec3 f_normal;
in vec2 f_coord;
in vec3 f_pos;
#include <common>
uniform sampler2D tex1;
vec3 apply_fog(vec3 color)
{
float sun_amount = 0.0;
if (lights_count >= 1U && lights[0].type == LIGHT_DIR)
sun_amount = max(dot(normalize(f_pos), normalize(-lights[0].dir)), 0.0);
vec3 fog_color_v = mix(fog_color, lights[0].color, pow(sun_amount, 30.0));
float fog_amount_v = 1.0 - min(1.0, exp(-length(f_pos) * fog_density));
return mix(color, fog_color_v, fog_amount_v);
}
float calc_light(vec3 light_dir)
{
vec3 normal = normalize(f_normal);
vec3 view_dir = normalize(vec3(0.0f, 0.0f, 0.0f) - f_pos);
vec3 halfway_dir = normalize(light_dir + view_dir);
float diffuse_v = max(dot(normal, light_dir), 0.0);
float specular_v = pow(max(dot(normal, halfway_dir), 0.0), 15.0);
return specular_v + diffuse_v;
}
float calc_point_light(light_s light)
{
vec3 light_dir = normalize(light.pos - f_pos);
float val = calc_light(light_dir);
float distance = length(light.pos - f_pos);
float atten = 1.0f / (1.0f + light.linear * distance + light.quadratic * (distance * distance));
return val * atten;
}
float calc_spot_light(light_s light)
{
vec3 light_dir = normalize(light.pos - f_pos);
float theta = dot(light_dir, normalize(-light.dir));
float epsilon = light.in_cutoff - light.out_cutoff;
float intensity = clamp((theta - light.out_cutoff) / epsilon, 0.0, 1.0);
float point = calc_point_light(light);
return point * intensity;
}
float calc_dir_light(light_s light)
{
vec3 light_dir = normalize(-light.dir);
return calc_light(light_dir);
}
void main()
{
vec3 result = ambient * 0.3 + param[0].rgb * emission;
for (uint i = 0U; i < lights_count; i++)
{
light_s light = lights[i];
float part = 0.0;
if (light.type == LIGHT_SPOT)
part = calc_spot_light(light);
else if (light.type == LIGHT_POINT)
part = calc_point_light(light);
else if (light.type == LIGHT_DIR)
part = calc_dir_light(light);
result += light.color * part;
}
vec4 tex_color = texture(tex1, f_coord);
vec3 c = apply_fog(result * tex_color.xyz);
gl_FragColor = vec4(c, tex_color.w);
}

8
shaders/mat_invalid.frag Normal file
View File

@@ -0,0 +1,8 @@
#version 330
#include <common>
void main()
{
gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
}

15
shaders/mat_nolight.frag Normal file
View File

@@ -0,0 +1,15 @@
#version 330
in vec3 f_normal;
in vec2 f_coord;
in vec3 f_pos;
uniform sampler2D tex1;
#include <common>
void main()
{
vec4 tex_color = texture(tex1, f_coord);
gl_FragColor = vec4(tex_color.xyz * ambient, tex_color.a);
}

91
shaders/mat_normal.frag Normal file
View File

@@ -0,0 +1,91 @@
#version 330
in vec3 f_normal;
in vec2 f_coord;
in vec3 f_pos;
in mat3 f_tbn;
in vec4 f_tangent;
uniform sampler2D tex1;
uniform sampler2D tex2;
#include <common>
vec3 apply_fog(vec3 color)
{
float sun_amount = 0.0;
if (lights_count >= 1U && lights[0].type == LIGHT_DIR)
sun_amount = max(dot(normalize(f_pos), normalize(-lights[0].dir)), 0.0);
vec3 fog_color_v = mix(fog_color, lights[0].color, pow(sun_amount, 30.0));
float fog_amount_v = 1.0 - min(1.0, exp(-length(f_pos) * fog_density));
return mix(color, fog_color_v, fog_amount_v);
}
float calc_light(vec3 light_dir)
{
//vec3 normal = normalize(f_normal);
vec3 normal = f_tbn * normalize(texture(tex2, f_coord).rgb * 2.0 - 1.0);
vec3 view_dir = normalize(vec3(0.0f, 0.0f, 0.0f) - f_pos);
vec3 halfway_dir = normalize(light_dir + view_dir);
float diffuse_v = max(dot(normal, light_dir), 0.0);
float specular_v = pow(max(dot(normal, halfway_dir), 0.0), 15.0) * 0.2;
return specular_v + diffuse_v;
}
float calc_point_light(light_s light)
{
vec3 light_dir = normalize(light.pos - f_pos);
float val = calc_light(light_dir);
float distance = length(light.pos - f_pos);
float atten = 1.0f / (1.0f + light.linear * distance + light.quadratic * (distance * distance));
return val * atten;
}
float calc_spot_light(light_s light)
{
vec3 light_dir = normalize(light.pos - f_pos);
float theta = dot(light_dir, normalize(-light.dir));
float epsilon = light.in_cutoff - light.out_cutoff;
float intensity = clamp((theta - light.out_cutoff) / epsilon, 0.0, 1.0);
float point = calc_point_light(light);
return point * intensity;
}
float calc_dir_light(light_s light)
{
vec3 light_dir = normalize(-light.dir);
return calc_light(light_dir);
}
void main()
{
vec3 result = ambient * 0.3 + param[0].rgb * emission;
for (uint i = 0U; i < lights_count; i++)
{
light_s light = lights[i];
float part = 0.0;
if (light.type == LIGHT_SPOT)
part = calc_spot_light(light);
else if (light.type == LIGHT_POINT)
part = calc_point_light(light);
else if (light.type == LIGHT_DIR)
part = calc_dir_light(light);
result += light.color * part;
}
vec4 tex_color = texture(tex1, f_coord);
vec3 c = apply_fog(result * tex_color.xyz);
gl_FragColor = vec4(c, tex_color.w);
// gl_FragColor = vec4(f_tangent.xyz, 1.0f);
}

8
shaders/mat_notex.frag Normal file
View File

@@ -0,0 +1,8 @@
#version 330
#include <common>
void main()
{
gl_FragColor = param[0];
}

28
shaders/simple.vert Normal file
View File

@@ -0,0 +1,28 @@
#version 330
in vec3 v_vert;
in vec3 v_normal;
in vec2 v_coord;
in vec4 v_tangent;
out vec3 f_normal;
out vec2 f_coord;
out vec3 f_pos;
out mat3 f_tbn;
out vec4 f_tangent;
#include <common>
void main()
{
gl_Position = (projection * modelview) * vec4(v_vert, 1.0f);
f_normal = modelviewnormal * v_normal;
f_coord = v_coord;
f_tangent = v_tangent;
f_pos = vec3(modelview * vec4(v_vert, 1.0f));
vec3 T = normalize(modelviewnormal * v_tangent.xyz);
vec3 B = normalize(modelviewnormal * cross(v_normal, v_tangent.xyz) * v_tangent.w);
vec3 N = normalize(modelviewnormal * v_normal);
f_tbn = mat3(T, B, N);
}

8
shaders/traction.frag Normal file
View File

@@ -0,0 +1,8 @@
#version 330
#include <common>
void main()
{
gl_FragColor = param[0];
}

12
shaders/traction.vert Normal file
View File

@@ -0,0 +1,12 @@
#version 330
in vec3 v_vert;
in vec3 v_normal;
in vec2 v_coord;
#include <common>
void main()
{
gl_Position = (projection * modelview) * vec4(v_vert, 1.0f);
}

View File

@@ -5,8 +5,7 @@ in vec3 v_color;
out vec3 f_color;
uniform mat4 modelview;
uniform mat4 projection;
#include <common>
void main()
{

View File

@@ -370,7 +370,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
// 3d terrain
if( false == Scratchpad.binary.terrain ) {
// if we're loading data from text .scn file convert and import
auto *instance { deserialize_model( Input, Scratchpad, nodedata ) };
auto *instance = deserialize_model( Input, Scratchpad, nodedata );
// model import can potentially fail
if( instance == nullptr ) { return; }
// go through submodels, and import them as shapes

View File

@@ -119,8 +119,8 @@ void CSkyDome::Render() {
if (!m_shader)
{
gl::shader vert("shaders/vbocolor.vert");
gl::shader frag("shaders/color.frag");
gl::shader vert("vbocolor.vert");
gl::shader frag("color.frag");
m_shader = std::make_unique<gl::program_mvp>(std::vector<std::reference_wrapper<const gl::shader>>({vert, frag}));
m_shader->init();
}

View File

@@ -66,6 +66,7 @@
#include <mutex>
#include <condition_variable>
#include <typeinfo>
#include <bitset>
#ifdef EU07_BUILD_STATIC
#define GLEW_STATIC