mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-08 21:00:03 +01:00
Merge pull request #245 from MaSzyna-EU07/split/2-materials
Split/2 materials
This commit is contained in:
2
gl/ubo.h
2
gl/ubo.h
@@ -62,7 +62,7 @@ namespace gl
|
||||
|
||||
static_assert(sizeof(scene_ubs) == 400, "bad size of ubs");
|
||||
|
||||
const size_t MAX_PARAMS = 3;
|
||||
const size_t MAX_PARAMS = 4;
|
||||
|
||||
struct model_ubs
|
||||
{
|
||||
|
||||
@@ -662,12 +662,176 @@ material_manager::create_from_text( std::string const &Name, std::string const &
|
||||
return materialhandle;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
opengl_material
|
||||
variant_of( opengl_material const &Source, std::string const &Suffix ) {
|
||||
|
||||
opengl_material variant;
|
||||
variant.textures = Source.textures;
|
||||
variant.texture_variants = Source.texture_variants;
|
||||
variant.params = Source.params;
|
||||
variant.params_state = Source.params_state;
|
||||
variant.shader = Source.shader;
|
||||
variant.opacity = Source.opacity;
|
||||
variant.selfillum = Source.selfillum;
|
||||
variant.shadow_rank = Source.shadow_rank;
|
||||
variant.glossiness = Source.glossiness;
|
||||
variant.name = Source.name + Suffix;
|
||||
variant.size = Source.size;
|
||||
variant.is_good = Source.is_good;
|
||||
variant.path = Source.path;
|
||||
return variant;
|
||||
}
|
||||
|
||||
// the params of a shader, as the shader keeps them
|
||||
using param_confs = decltype( gl::shader::param_conf );
|
||||
|
||||
// whether another param of the shader lies on a component of the named one, which a value set for that one would change too
|
||||
bool
|
||||
shares_slot( param_confs const &Conf, std::string const &Name ) {
|
||||
|
||||
auto const own { Conf.find( Name ) };
|
||||
if( own == Conf.end() ) {
|
||||
return false;
|
||||
}
|
||||
return std::ranges::any_of(
|
||||
Conf,
|
||||
[ &Name, &own ]( auto const &Entry ) {
|
||||
return Entry.first != Name
|
||||
&& Entry.second.location == own->second.location
|
||||
&& Entry.second.offset < own->second.offset + own->second.size
|
||||
&& own->second.offset < Entry.second.offset + Entry.second.size; } );
|
||||
}
|
||||
|
||||
// the highlights of a copy of a material damped and its weathering on
|
||||
void
|
||||
make_matte( opengl_material &Variant ) {
|
||||
|
||||
Variant.glossiness = 0.1f;
|
||||
if( !Variant.shader ) {
|
||||
return;
|
||||
}
|
||||
for( auto const &[ key, value ] : std::vector<std::pair<std::string, glm::vec4>>{ { "weathering", glm::vec4{ 1.f } } } ) {
|
||||
auto const entry { Variant.shader->param_conf.find( key ) };
|
||||
if( entry == Variant.shader->param_conf.end()
|
||||
|| shares_slot( Variant.shader->param_conf, key ) ) {
|
||||
continue;
|
||||
}
|
||||
auto &slot { Variant.params[ entry->second.location ] };
|
||||
auto const offset { static_cast<glm::length_t>( entry->second.offset ) };
|
||||
auto const size { static_cast<glm::length_t>( entry->second.size ) };
|
||||
for( glm::length_t i = 0; i < size; ++i ) {
|
||||
slot[ offset + i ] = value[ i ];
|
||||
}
|
||||
std::erase_if(
|
||||
Variant.params_state,
|
||||
[ &entry ]( gl::shader::param_entry const &State ) {
|
||||
return State.location == entry->second.location && State.offset == entry->second.offset; } );
|
||||
}
|
||||
}
|
||||
|
||||
// the colour in the rgb of the slot of the weathering of a copy of a material, which tells the shader to tint by its sign. returns:
|
||||
// whether the shader can tint it, the weathering and the tint alone in that slot
|
||||
bool
|
||||
make_tinted( opengl_material &Variant, glm::vec3 const &Colour ) {
|
||||
|
||||
if( !Variant.shader ) {
|
||||
return false;
|
||||
}
|
||||
auto const &conf { Variant.shader->param_conf };
|
||||
auto const weathering { conf.find( "weathering" ) };
|
||||
if( auto const tint { conf.find( "tint" ) };
|
||||
weathering == conf.end()
|
||||
|| tint == conf.end()
|
||||
|| weathering->second.offset != 3
|
||||
|| tint->second.location != weathering->second.location
|
||||
|| tint->second.offset != 0
|
||||
|| std::ranges::any_of(
|
||||
conf,
|
||||
[ &weathering, &tint ]( auto const &Entry ) {
|
||||
return Entry.first != weathering->first && Entry.first != tint->first && Entry.second.location == weathering->second.location; } ) ) {
|
||||
return false;
|
||||
}
|
||||
auto const location { weathering->second.location };
|
||||
Variant.params[ location ] = glm::vec4{ Colour, -1.f };
|
||||
std::erase_if(
|
||||
Variant.params_state,
|
||||
[ location ]( gl::shader::param_entry const &State ) {
|
||||
return State.location == location; } );
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
material_handle
|
||||
material_manager::create_matte( material_handle const Material ) {
|
||||
|
||||
if( Material == null_handle || Material >= m_materials.size() ) {
|
||||
return Material;
|
||||
}
|
||||
if( auto const lookup { m_mattes.find( Material ) }; lookup != m_mattes.end() ) {
|
||||
return lookup->second;
|
||||
}
|
||||
auto matte { variant_of( m_materials[ Material ], ":matte" ) };
|
||||
make_matte( matte );
|
||||
auto const mattehandle { static_cast<material_handle>( m_materials.size() ) };
|
||||
m_materials.emplace_back( std::move( matte ) );
|
||||
m_mattes.emplace( Material, mattehandle );
|
||||
return mattehandle;
|
||||
}
|
||||
|
||||
material_handle
|
||||
material_manager::create_tinted( material_handle const Material, glm::vec3 const &Colour ) {
|
||||
|
||||
if( Material == null_handle || Material >= m_materials.size() || !m_materials[ Material ].shader ) {
|
||||
return Material;
|
||||
}
|
||||
auto const key { std::make_tuple( Material, Colour.r, Colour.g, Colour.b ) };
|
||||
if( auto const lookup { m_tints.find( key ) }; lookup != m_tints.end() ) {
|
||||
return lookup->second;
|
||||
}
|
||||
auto tinted { variant_of( m_materials[ Material ], ":tinted" ) };
|
||||
if( false == make_tinted( tinted, Colour ) ) {
|
||||
return Material;
|
||||
}
|
||||
auto const tintedhandle { static_cast<material_handle>( m_materials.size() ) };
|
||||
m_materials.emplace_back( std::move( tinted ) );
|
||||
m_tints.emplace( key, tintedhandle );
|
||||
return tintedhandle;
|
||||
}
|
||||
|
||||
void
|
||||
material_manager::update_variants( bool const Weather ) {
|
||||
|
||||
// the copies don't update themselves, their names aren't files to read again
|
||||
auto const changed = [&]( material_handle const Source ) {
|
||||
auto const &source { m_materials[ Source ] };
|
||||
return Weather ? source.update_on_weather_change : source.update_on_season_change; };
|
||||
for( auto const &[ source, matte ] : m_mattes ) {
|
||||
if( changed( source ) ) {
|
||||
auto variant { variant_of( m_materials[ source ], ":matte" ) };
|
||||
make_matte( variant );
|
||||
m_materials[ matte ] = std::move( variant );
|
||||
}
|
||||
}
|
||||
for( auto const &[ key, tinted ] : m_tints ) {
|
||||
auto const source { std::get<0>( key ) };
|
||||
if( changed( source ) ) {
|
||||
auto variant { variant_of( m_materials[ source ], ":tinted" ) };
|
||||
make_tinted( variant, glm::vec3 { std::get<1>( key ), std::get<2>( key ), std::get<3>( key ) } );
|
||||
m_materials[ tinted ] = std::move( variant );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
material_manager::on_weather_change() {
|
||||
|
||||
for( auto &material : m_materials ) {
|
||||
if( material.update_on_weather_change ) { material.update(); }
|
||||
}
|
||||
update_variants( true );
|
||||
}
|
||||
|
||||
void
|
||||
@@ -676,6 +840,7 @@ material_manager::on_season_change() {
|
||||
for( auto &material : m_materials ) {
|
||||
if( material.update_on_season_change ) { material.update(); }
|
||||
}
|
||||
update_variants( false );
|
||||
}
|
||||
|
||||
// checks whether specified material is in the material bank. returns handle to the material, or a null handle
|
||||
|
||||
@@ -142,6 +142,13 @@ public:
|
||||
// material described by provided text (the content of a .mat file), not kept in a file. returns: handle to the material or null_handle
|
||||
material_handle
|
||||
create_from_text( std::string const &Name, std::string const &Definition );
|
||||
// copy of provided material with its specular highlights and reflections damped. returns: handle to the copy, made once per material
|
||||
material_handle
|
||||
create_matte( material_handle const Material );
|
||||
// copy of provided material with its texture tinted to the colour as far as the userdata of the vertices says. returns: handle to
|
||||
// the copy, made once per material and colour; the material itself when its shader can't tint it
|
||||
material_handle
|
||||
create_tinted( material_handle const Material, glm::vec3 const &Colour );
|
||||
opengl_material const &
|
||||
material( material_handle const Material ) const { return m_materials[ Material ]; }
|
||||
opengl_material &
|
||||
@@ -161,6 +168,9 @@ private:
|
||||
// checks whether specified texture is in the texture bank. returns texture id, or npos.
|
||||
material_handle
|
||||
find_in_databank( std::string const &Materialname ) const;
|
||||
// the matte and tinted copies of the materials changed with the weather or the season made again from them, under their handles
|
||||
void
|
||||
update_variants( bool const Weather );
|
||||
public:
|
||||
// checks whether specified file exists. returns name of the located file, or empty string.
|
||||
static std::pair<std::string, std::string>
|
||||
@@ -170,6 +180,8 @@ private:
|
||||
// members:
|
||||
material_sequence m_materials;
|
||||
index_map m_materialmappings;
|
||||
std::unordered_map<material_handle, material_handle> m_mattes;
|
||||
std::map<std::tuple<material_handle, float, float, float>, material_handle> m_tints;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -318,6 +318,20 @@ geometry_bank::append( gfx::vertex_array &Vertices, userdata_array &Userdata, gf
|
||||
return replace( Vertices, Userdata, Geometry, gfx::geometry_bank::chunk( Geometry ).vertices.size() );
|
||||
}
|
||||
|
||||
void
|
||||
geometry_bank::erase( gfx::geometry_handle const &Geometry ) {
|
||||
|
||||
if( ( Geometry.chunk == 0 ) || ( Geometry.chunk > m_chunks.size() ) ) { return; }
|
||||
|
||||
auto &chunk = gfx::geometry_bank::chunk( Geometry );
|
||||
if( chunk.vertices.empty() && chunk.indices.empty() ) { return; }
|
||||
|
||||
gfx::vertex_array().swap( chunk.vertices );
|
||||
gfx::index_array().swap( chunk.indices );
|
||||
gfx::userdata_array().swap( chunk.userdata );
|
||||
replace_( Geometry );
|
||||
}
|
||||
|
||||
// draws geometry stored in specified chunk
|
||||
std::size_t
|
||||
geometry_bank::draw( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) {
|
||||
@@ -360,6 +374,15 @@ geometry_bank::vertices( gfx::geometry_handle const &Geometry ) const {
|
||||
return geometry_bank::chunk( Geometry ).vertices;
|
||||
}
|
||||
|
||||
// kind of geometry of specified chunk
|
||||
unsigned int
|
||||
geometry_bank::primitive( gfx::geometry_handle const &Geometry ) const {
|
||||
|
||||
if( ( Geometry.chunk == 0 ) || ( Geometry.chunk > m_chunks.size() ) ) { return no_primitive; }
|
||||
|
||||
return geometry_bank::chunk( Geometry ).type;
|
||||
}
|
||||
|
||||
// provides direct access to vertex user data of specfied chunk
|
||||
userdata_array const &
|
||||
geometry_bank::userdata( gfx::geometry_handle const &Geometry ) const {
|
||||
@@ -418,6 +441,14 @@ geometrybank_manager::append( gfx::vertex_array &Vertices, userdata_array &Userd
|
||||
|
||||
return bank( Geometry ).first->append( Vertices, Userdata, Geometry );
|
||||
}
|
||||
|
||||
void
|
||||
geometrybank_manager::erase( gfx::geometry_handle const &Geometry ) {
|
||||
|
||||
if( ( Geometry.bank == 0 ) || ( Geometry.bank > m_geometrybanks.size() ) ) { return; }
|
||||
|
||||
bank( Geometry ).first->erase( Geometry );
|
||||
}
|
||||
// draws geometry stored in specified chunk
|
||||
void
|
||||
geometrybank_manager::draw( gfx::geometry_handle const &Geometry, unsigned int const Streams ) {
|
||||
@@ -483,6 +514,15 @@ geometrybank_manager::vertices( gfx::geometry_handle const &Geometry ) const {
|
||||
return bank( Geometry ).first->vertices( Geometry );
|
||||
}
|
||||
|
||||
// kind of geometry of specified chunk
|
||||
unsigned int
|
||||
geometrybank_manager::primitive( gfx::geometry_handle const &Geometry ) const {
|
||||
|
||||
if( ( Geometry.bank == 0 ) || ( Geometry.bank > m_geometrybanks.size() ) ) { return geometry_bank::no_primitive; }
|
||||
|
||||
return bank( Geometry ).first->primitive( Geometry );
|
||||
}
|
||||
|
||||
// provides direct access to vertex user data of specfied chunk
|
||||
gfx::userdata_array const &
|
||||
geometrybank_manager::userdata( gfx::geometry_handle const &Geometry ) const {
|
||||
|
||||
@@ -117,6 +117,7 @@ public:
|
||||
auto replace( gfx::vertex_array &Vertices, gfx::userdata_array& Userdata, gfx::geometry_handle const &Geometry, std::size_t const Offset = 0 ) -> bool;
|
||||
// adds supplied vertex data at the end of specified chunk
|
||||
auto append( gfx::vertex_array &Vertices, gfx::userdata_array& Userdata, gfx::geometry_handle const &Geometry ) -> bool;
|
||||
void erase( gfx::geometry_handle const &Geometry );
|
||||
// draws geometry stored in specified chunk
|
||||
auto draw( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams = basic_streams ) -> std::size_t;
|
||||
// draws geometry stored in specified chunk N times via glDrawElementsInstanced*
|
||||
@@ -138,6 +139,9 @@ public:
|
||||
auto vertices( gfx::geometry_handle const &Geometry ) const -> gfx::vertex_array const &;
|
||||
// provides direct access to vertex user data of specfied chunk
|
||||
auto userdata( gfx::geometry_handle const &Geometry ) const -> gfx::userdata_array const &;
|
||||
// kind of geometry of specified chunk, GL_TRIANGLES, GL_TRIANGLE_STRIP...; no_primitive for a handle to no chunk
|
||||
auto primitive( gfx::geometry_handle const &Geometry ) const -> unsigned int;
|
||||
static constexpr unsigned int no_primitive { ~0u };
|
||||
|
||||
protected:
|
||||
// types:
|
||||
@@ -220,6 +224,7 @@ public:
|
||||
auto replace( gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, std::size_t const Offset = 0 ) -> bool;
|
||||
// adds supplied vertex data at the end of specified chunk
|
||||
auto append( gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry ) -> bool;
|
||||
void erase( gfx::geometry_handle const &Geometry );
|
||||
// draws geometry stored in specified chunk
|
||||
void draw( gfx::geometry_handle const &Geometry, unsigned int const Streams = basic_streams );
|
||||
// draws geometry stored in specified chunk InstanceCount times via GPU instancing.
|
||||
@@ -238,6 +243,8 @@ public:
|
||||
auto vertices( gfx::geometry_handle const &Geometry ) const -> gfx::vertex_array const &;
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
auto userdata( gfx::geometry_handle const &Geometry ) const -> gfx::userdata_array const &;
|
||||
// kind of geometry of specified chunk
|
||||
auto primitive( gfx::geometry_handle const &Geometry ) const -> unsigned int;
|
||||
// sets target texture unit for the texture data stream
|
||||
auto units() -> gfx::stream_units & { return m_units; }
|
||||
// provides access to primitives count
|
||||
|
||||
@@ -33,7 +33,8 @@ opengl33_vaogeometrybank::replace_( gfx::geometry_handle const &Geometry ) {
|
||||
auto &chunkrecord = m_chunkrecords[ Geometry.chunk - 1 ];
|
||||
chunkrecord.is_good = false;
|
||||
// if the overall length of the chunk didn't change we can get away with reusing the old buffer...
|
||||
if( geometry_bank::chunk( Geometry ).vertices.size() != chunkrecord.vertex_count ) {
|
||||
if( ( geometry_bank::chunk( Geometry ).vertices.size() != chunkrecord.vertex_count )
|
||||
|| ( geometry_bank::chunk( Geometry ).userdata.empty() == chunkrecord.has_userdata ) ) {
|
||||
// ...but otherwise we'll need to allocate a new one
|
||||
// TBD: we could keep and reuse the old buffer also if the new chunk is smaller than the old one,
|
||||
// but it'd require some extra tracking and work to keep all chunks up to date; also wasting vram; may be not worth it?
|
||||
|
||||
@@ -2201,8 +2201,13 @@ bool opengl33_renderer::Append(gfx::vertex_array &Vertices, gfx::userdata_array
|
||||
return m_geometry.append(Vertices, Userdata, Geometry);
|
||||
}
|
||||
|
||||
void opengl33_renderer::Erase(gfx::geometry_handle const &Geometry)
|
||||
{
|
||||
m_geometry.erase(Geometry);
|
||||
}
|
||||
|
||||
// provides direct access to index data of specfied chunk
|
||||
gfx::index_array const & opengl33_renderer::Indices(gfx::geometry_handle const &Geometry) const
|
||||
gfx::index_array const & opengl33_renderer::Indices(gfx::geometry_handle const &Geometry) const
|
||||
{
|
||||
return m_geometry.indices(Geometry);
|
||||
}
|
||||
@@ -2218,6 +2223,12 @@ gfx::userdata_array const &opengl33_renderer::UserData(const gfx::geometry_handl
|
||||
return m_geometry.userdata(Geometry);
|
||||
}
|
||||
|
||||
int opengl33_renderer::Primitive(gfx::geometry_handle const &Geometry) const
|
||||
{
|
||||
auto const primitive{m_geometry.primitive(Geometry)};
|
||||
return primitive == gfx::geometry_bank::no_primitive ? -1 : static_cast<int>(primitive);
|
||||
}
|
||||
|
||||
// material methods
|
||||
material_handle opengl33_renderer::Fetch_Material(std::string const &Filename, bool const Loadnow)
|
||||
{
|
||||
@@ -2225,6 +2236,18 @@ material_handle opengl33_renderer::Fetch_Material(std::string const &Filename, b
|
||||
return m_materials.create(Filename, Loadnow);
|
||||
}
|
||||
|
||||
material_handle opengl33_renderer::Matte_Material(material_handle const Material)
|
||||
{
|
||||
|
||||
return m_materials.create_matte(Material);
|
||||
}
|
||||
|
||||
material_handle opengl33_renderer::Tinted_Material(material_handle const Material, glm::vec3 const &Colour)
|
||||
{
|
||||
|
||||
return m_materials.create_tinted(Material, Colour);
|
||||
}
|
||||
|
||||
std::shared_ptr<gl::program> opengl33_renderer::Fetch_Shader(const std::string &name)
|
||||
{
|
||||
auto it = m_shaders.find(name);
|
||||
|
||||
@@ -66,6 +66,7 @@ class opengl33_renderer : public gfx_renderer {
|
||||
bool Replace(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type, const std::size_t Offset = 0) override;
|
||||
// adds supplied vertex data at the end of specified chunk
|
||||
bool Append(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type) override;
|
||||
void Erase( gfx::geometry_handle const &Geometry ) override;
|
||||
// provides direct access to index data of specfied chunk
|
||||
gfx::index_array const &
|
||||
Indices( gfx::geometry_handle const &Geometry ) const override;
|
||||
@@ -75,9 +76,15 @@ class opengl33_renderer : public gfx_renderer {
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
gfx::userdata_array const &
|
||||
UserData( gfx::geometry_handle const &Geometry ) const override;
|
||||
int
|
||||
Primitive( gfx::geometry_handle const &Geometry ) const override;
|
||||
// material methods
|
||||
material_handle
|
||||
Fetch_Material( std::string const &Filename, bool const Loadnow = true ) override;
|
||||
material_handle
|
||||
Matte_Material( material_handle const Material ) override;
|
||||
material_handle
|
||||
Tinted_Material( material_handle const Material, glm::vec3 const &Colour ) override;
|
||||
void
|
||||
Bind_Material( material_handle const Material, TSubModel const *sm = nullptr, lighting_data const *lighting = nullptr ) override;
|
||||
IMaterial const *
|
||||
|
||||
@@ -1758,6 +1758,11 @@ bool opengl_renderer::Append(gfx::vertex_array &Vertices, gfx::userdata_array &U
|
||||
return m_geometry.append( Vertices, Userdata, Geometry );
|
||||
}
|
||||
|
||||
void opengl_renderer::Erase( gfx::geometry_handle const &Geometry )
|
||||
{
|
||||
m_geometry.erase( Geometry );
|
||||
}
|
||||
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
gfx::index_array const &
|
||||
opengl_renderer::Indices( gfx::geometry_handle const &Geometry ) const {
|
||||
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
bool Replace(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type, const std::size_t Offset = 0) override;
|
||||
// adds supplied vertex data at the end of specified chunk
|
||||
bool Append(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type) override;
|
||||
void Erase( gfx::geometry_handle const &Geometry ) override;
|
||||
// provides direct access to index data of specfied chunk
|
||||
gfx::index_array const &
|
||||
Indices( gfx::geometry_handle const &Geometry ) const override;
|
||||
|
||||
@@ -59,16 +59,26 @@ public:
|
||||
virtual auto Replace(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type, const std::size_t Offset = 0) -> bool = 0;
|
||||
// adds supplied vertex data at the end of specified chunk
|
||||
virtual auto Append(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type) -> bool = 0;
|
||||
// empties specified chunk, its handle stays valid to be filled again
|
||||
virtual void Erase( gfx::geometry_handle const & /*Geometry*/ ) {
|
||||
// a renderer which keeps no chunks of its own has none to empty
|
||||
}
|
||||
// provides direct access to index data of specfied chunk
|
||||
virtual auto Indices( gfx::geometry_handle const &Geometry ) const->gfx::index_array const & = 0;
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
virtual auto Vertices( gfx::geometry_handle const &Geometry ) const ->gfx::vertex_array const & = 0;
|
||||
// provides direct access to vertex user data of specfied chunk
|
||||
virtual auto UserData( gfx::geometry_handle const &Geometry ) const ->gfx::userdata_array const & = 0;
|
||||
// kind of geometry of specified chunk, -1 when the renderer doesn't tell
|
||||
virtual auto Primitive( gfx::geometry_handle const &Geometry ) const -> int { return -1; }
|
||||
// material methods
|
||||
virtual auto Fetch_Material( std::string const &Filename, bool const Loadnow = true ) -> material_handle = 0;
|
||||
virtual void Bind_Material( material_handle const Material, TSubModel const *sm = nullptr, lighting_data const *lighting = nullptr ) = 0;
|
||||
virtual auto Material( material_handle const Material ) const -> IMaterial const * = 0;
|
||||
// the same material with its highlights damped, for faces which aren't polished like the surfaces they are cut from. backends which can't make one give back the material itself
|
||||
virtual auto Matte_Material( material_handle const Material ) -> material_handle { return Material; }
|
||||
// the same material with its texture tinted by the colour, as far as the userdata of the vertices says. backends which can't make one give back the material itself
|
||||
virtual auto Tinted_Material( material_handle const Material, glm::vec3 const &Colour ) -> material_handle { return Material; }
|
||||
// heightmap terrain: material of a chunk blending the materials of up to 8 layers by their weights.
|
||||
// Weights: (Samples + 1)^2 values per layer, planar, rows of growing z, the weights of a sample adding up to 255; null with a single layer.
|
||||
// Placement: corner of the chunk (x, z) in the texture coordinates of its mesh, and the size of the chunk.
|
||||
|
||||
@@ -9,6 +9,11 @@ uniform sampler2D headlightmap;
|
||||
|
||||
float glossiness = 1.0;
|
||||
float metalic = 0.0;
|
||||
in vec4 UserData;
|
||||
// a slot of its own, the shaders of the materials using all of param[2]: how weathered the steel is as far as the userdata of
|
||||
// its vertices says; below 0: the texture tinted to the colour of tint as far instead
|
||||
#param (weathering, 3, 3, 1, zero)
|
||||
#param (tint, 3, 0, 3, one)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Lighting balance tunables - tweak these to control overall scene
|
||||
@@ -285,6 +290,19 @@ vec3 apply_lights(vec3 fragcolor, vec3 fragnormal, vec3 texturecolor, float refl
|
||||
{
|
||||
// Diffuse colour is applied once, to the albedo; the light terms below are not scaled by it again
|
||||
texturecolor *= material_diffuse();
|
||||
float weathered = (param[3].w > 0.0 ? clamp(param[3].w * UserData.x, 0.0, 1.0) : 0.0);
|
||||
float tinted = (param[3].w < 0.0 ? clamp(-param[3].w * UserData.x, 0.0, 1.0) : 0.0);
|
||||
// a tint only scales the colour of the texture, the steel keeps its own polish
|
||||
float polished = weathered * smoothstep(0.03, 0.12, dot(texturecolor, vec3(0.2126, 0.7152, 0.0722)));
|
||||
float weatheredluma = min(dot(texturecolor, vec3(0.2126, 0.7152, 0.0722)), 0.05);
|
||||
vec3 unused = texturecolor * (weatheredluma / max(dot(texturecolor, vec3(0.2126, 0.7152, 0.0722)), 1e-4));
|
||||
unused = mix(unused, vec3(1.0, 0.82, 0.74) * (weatheredluma / 0.8525), 0.5);
|
||||
texturecolor = mix(texturecolor, unused, smoothstep(0.0, 0.4, weathered));
|
||||
texturecolor = (tinted > 0.0 ? texturecolor * mix(vec3(1.0), param[3].rgb, tinted) : texturecolor);
|
||||
specularity = mix(specularity, min(specularity, 0.03), smoothstep(0.0, 0.4, polished));
|
||||
metalic = mix(metalic, 0.0, polished);
|
||||
glossiness = mix(glossiness, min(glossiness, 0.06 * abs(param[1].w)), polished);
|
||||
reflectivity = mix(reflectivity, min(reflectivity, 0.08 * param[1].z), smoothstep(0.0, 0.4, polished));
|
||||
// Scale ambient before it gets tinted by the texture.
|
||||
// Sun, headlights and emission are added afterwards so they are NOT
|
||||
// attenuated by AMBIENT_SCALE - this only dims the indirect term.
|
||||
|
||||
Reference in New Issue
Block a user