16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-19 06:29:18 +02:00

material work, use multibind and dsa in main texture binding

This commit is contained in:
milek7
2018-07-19 00:20:42 +02:00
parent ee16821509
commit a53224b47d
16 changed files with 128 additions and 178 deletions

View File

@@ -285,7 +285,8 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
std::replace(material.begin(), material.end(), '\\', '/');
if (material == "none")
{ // rysowanie podanym kolorem
m_material = null_handle;
Name_Material("colored");
m_material = GfxRenderer.Fetch_Material(m_materialname);
iFlags |= 0x10; // rysowane w cyklu nieprzezroczystych
}
else if (material.find("replacableskin") != material.npos)
@@ -338,6 +339,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
if (m_material != null_handle)
{
opengl_material &mat = GfxRenderer.Material(m_material);
// if material have opacity set, replace submodel opacity with it
if (!std::isnan(mat.opacity))
{
@@ -347,6 +349,10 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
else
iFlags |= 0x10; // opaque
}
// and same thing with selfillum
if (!std::isnan(mat.selfillum))
fLight = mat.selfillum;
}
// visibility range
@@ -1690,6 +1696,15 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
else
iFlags |= 0x10; // opaque
}
if (m_material != null_handle)
{
opengl_material &mat = GfxRenderer.Material(m_material);
// replace submodel selfillum with material one
if (!std::isnan(mat.selfillum))
fLight = mat.selfillum;
}
}
else {
ErrorLog( "Bad model: reference to nonexistent texture index in sub-model" + ( pName.empty() ? "" : " \"" + pName + "\"" ), logtype::model );
@@ -1697,7 +1712,12 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
}
}
else
m_material = iTexture;
{
if (iTexture == 0)
m_material = GfxRenderer.Fetch_Material("colored");
else
m_material = iTexture;
}
b_aAnim = b_Anim; // skopiowanie animacji do drugiego cyklu

View File

@@ -578,7 +578,7 @@ opengl_texture::bind(size_t unit) {
return false;
}
if (m_units[unit] == id)
if (units[unit] == id)
return true;
if (GLEW_ARB_direct_state_access)
@@ -595,7 +595,7 @@ opengl_texture::bind(size_t unit) {
glBindTexture(target, id);
}
m_units[unit] = id;
units[unit] = id;
return true;
}
@@ -620,13 +620,13 @@ void opengl_texture::unbind(size_t unit)
void opengl_texture::reset_unit_cache()
{
for( auto &unit : m_units ) {
for( auto &unit : units ) {
unit = 0;
}
m_activeunit = -1;
}
std::array<GLuint, gl::MAX_TEXTURES + 2> opengl_texture::m_units = { 0 };
std::array<GLuint, gl::MAX_TEXTURES + 2> opengl_texture::units = { 0 };
GLint opengl_texture::m_activeunit = -1;
std::unordered_map<GLint, int> opengl_texture::precompressed_formats =
@@ -1006,7 +1006,7 @@ texture_manager::create(std::string Filename, bool const Loadnow , GLint fh) {
void
texture_manager::bind( std::size_t const Unit, texture_handle const Texture ) {
m_textures[ Texture ].second = m_garbagecollector.timestamp();
mark_as_used(Texture);
if (Texture != null_handle)
texture(Texture).bind(Unit);
@@ -1014,6 +1014,13 @@ texture_manager::bind( std::size_t const Unit, texture_handle const Texture ) {
opengl_texture::unbind(Unit);
}
opengl_texture &texture_manager::mark_as_used(const texture_handle Texture)
{
auto &pair = m_textures[ Texture ];
pair.second = m_garbagecollector.timestamp();
return *pair.first;
}
void
texture_manager::delete_textures() {
for( auto const &texture : m_textures ) {

View File

@@ -57,6 +57,7 @@ struct opengl_texture {
GLint components_hint; // components that material wants
GLenum target = GL_TEXTURE_2D;
static std::array<GLuint, gl::MAX_TEXTURES + 2> units;
private:
// methods
@@ -91,7 +92,6 @@ private:
static std::unordered_map<GLint, GLint> drivercompressed_formats;
static std::unordered_map<GLint, std::unordered_map<GLint, GLint>> mapping;
static std::array<GLuint, gl::MAX_TEXTURES + 2> m_units;
static GLint m_activeunit;
};
@@ -109,6 +109,7 @@ public:
// binds specified texture to specified texture unit
void
bind( std::size_t const Unit, texture_handle const Texture );
opengl_texture& mark_as_used(texture_handle const Texture);
// provides direct access to specified texture object
opengl_texture &
texture( texture_handle const Texture ) const { return *(m_textures[ Texture ].first); }

View File

@@ -104,11 +104,7 @@ void gl::shader::parse_texture_entries(std::string &str)
if (arg == 0)
token_ss >> name;
else if (arg == 1)
{
token_ss >> conf.id;
if (conf.id >= gl::MAX_TEXTURES)
log_error("invalid texture binding: " + std::to_string(conf.id));
}
else if (arg == 2)
{
std::string comp;
@@ -122,7 +118,14 @@ void gl::shader::parse_texture_entries(std::string &str)
}
if (arg == 3)
texture_conf.emplace(std::make_pair(name, conf));
{
if (name.empty())
log_error("empty name");
else if (conf.id >= gl::MAX_TEXTURES)
log_error("invalid texture binding: " + std::to_string(conf.id));
else
texture_conf.emplace(std::make_pair(name, conf));
}
else
log_error("invalid argument count to #texture");
@@ -155,11 +158,7 @@ void gl::shader::parse_param_entries(std::string &str)
if (arg == 0)
token_ss >> name;
else if (arg == 1)
{
token_ss >> conf.location;
if (conf.location >= gl::MAX_PARAMS)
log_error("invalid param binding: " + std::to_string(conf.location));
}
else if (arg == 2)
token_ss >> conf.offset;
else if (arg == 3)
@@ -176,7 +175,18 @@ void gl::shader::parse_param_entries(std::string &str)
}
if (arg == 5)
param_conf.emplace(std::make_pair(name, conf));
{
if (name.empty())
log_error("empty name");
else if (conf.location >= gl::MAX_PARAMS)
log_error("invalid param binding: " + std::to_string(conf.location));
else if (conf.offset > 3)
log_error("invalid offset: " + std::to_string(conf.offset));
else if (conf.offset + conf.size > 4)
log_error("invalid size: " + std::to_string(conf.size));
else
param_conf.emplace(std::make_pair(name, conf));
}
else
log_error("invalid argument count to #param");

View File

@@ -31,7 +31,7 @@ namespace gl
#pragma pack(push, 1)
const size_t MAX_TEXTURES = 4;
const size_t MAX_TEXTURES = 8;
struct scene_ubs
{
@@ -91,7 +91,7 @@ namespace gl
static_assert(sizeof(light_element_ubs) == 64, "bad size of ubs");
const size_t MAX_LIGHTS = 4;
const size_t MAX_LIGHTS = 8;
struct light_ubs
{

View File

@@ -15,6 +15,12 @@ http://mozilla.org/MPL/2.0/.
#include "utilities.h"
#include "Logs.h"
opengl_material::opengl_material()
{
for (size_t i = 0; i < params.size(); i++)
params[i] = glm::vec4(std::numeric_limits<float>::quiet_NaN());
}
bool
opengl_material::deserialize( cParser &Input, bool const Loadnow ) {
parse_info = std::make_unique<parse_info_s>();
@@ -34,12 +40,6 @@ void opengl_material::log_error(const std::string &str)
void opengl_material::finalize(bool Loadnow)
{
if (!shader)
{
log_error("shader not specified, assuming \"default\"");
shader = GfxRenderer.Fetch_Shader("default");
}
if (parse_info)
{
for (auto it : parse_info->tex_mapping)
@@ -59,7 +59,7 @@ void opengl_material::finalize(bool Loadnow)
{
key.erase(0, 1);
key.pop_back();
if (shader->texture_conf.find(key) != shader->texture_conf.end())
if (shader && shader->texture_conf.find(key) != shader->texture_conf.end())
textures[shader->texture_conf[key].id] = GfxRenderer.Fetch_Texture(value, Loadnow);
else
log_error("unknown texture binding: " + key);
@@ -68,6 +68,25 @@ void opengl_material::finalize(bool Loadnow)
log_error("unrecognized texture binding: " + key);
}
if (!shader)
{
if (textures[0] == null_handle)
{
log_error("shader not specified, assuming \"default_0\"");
shader = GfxRenderer.Fetch_Shader("default_0");
}
else if (textures[1] == null_handle)
{
log_error("shader not specified, assuming \"default_1\"");
shader = GfxRenderer.Fetch_Shader("default_1");
}
else if (textures[2] == null_handle)
{
log_error("shader not specified, assuming \"default_2\"");
shader = GfxRenderer.Fetch_Shader("default_2");
}
}
for (auto it : parse_info->param_mapping)
{
std::string key = it.first;
@@ -319,6 +338,10 @@ material_manager::create( std::string const &Filename, bool const Loadnow ) {
// if there's also no texture, give up
return null_handle;
}
// material would attach default shader anyway, but it would spit to error log
material.shader = GfxRenderer.Fetch_Shader("default_1");
// use texture path and name to tell the newly created materials apart
filename = GfxRenderer.Texture( material.textures[0] ).name;
erase_extension( filename );

View File

@@ -20,7 +20,7 @@ typedef int material_handle;
// for modern opengl this translates to set of attributes for shaders
struct opengl_material {
std::array<texture_handle, gl::MAX_TEXTURES> textures = { null_handle };
std::array<glm::vec4, gl::MAX_PARAMS> params = { glm::vec4(std::numeric_limits<float>::quiet_NaN()) };
std::array<glm::vec4, gl::MAX_PARAMS> params;
std::vector<gl::shader::param_entry> params_state;
std::shared_ptr<gl::program> shader;
@@ -30,7 +30,7 @@ struct opengl_material {
std::string name;
// constructors
opengl_material() = default;
opengl_material();
// methods
bool

View File

@@ -1101,15 +1101,17 @@ void opengl_renderer::Bind_Material(material_handle const Material, TSubModel *s
{
gl::shader::param_entry entry = material.params_state[i];
glm::vec4 src;
if (entry.defaultparam == gl::shader::defaultparam_e::ambient)
src = sm->f4Ambient;
else if (entry.defaultparam == gl::shader::defaultparam_e::diffuse)
src = sm->f4Diffuse;
else if (entry.defaultparam == gl::shader::defaultparam_e::specular)
src = sm->f4Specular;
else
continue;
glm::vec4 src(1.0f);
if (sm)
{
if (entry.defaultparam == gl::shader::defaultparam_e::ambient)
src = sm->f4Ambient;
else if (entry.defaultparam == gl::shader::defaultparam_e::diffuse)
src = sm->f4Diffuse;
else if (entry.defaultparam == gl::shader::defaultparam_e::specular)
src = sm->f4Specular;
}
for (size_t j = 0; j < entry.size; j++)
model_ubs.param[entry.location][entry.offset + j] = src[j];
@@ -1125,18 +1127,24 @@ void opengl_renderer::Bind_Material(material_handle const Material, TSubModel *s
if (GLEW_ARB_multi_bind)
{
GLuint textures[gl::MAX_TEXTURES] = { 0 };
GLuint lastdiff = 0;
size_t i;
for (i = 0; i < gl::MAX_TEXTURES; i++)
if (material.textures[i] != null_handle)
{
opengl_texture &tex = m_textures.texture(material.textures[i]);
opengl_texture &tex = m_textures.mark_as_used(material.textures[i]);
tex.create();
textures[i] = tex.id;
if (opengl_texture::units[i] != tex.id)
{
opengl_texture::units[i] = tex.id;
lastdiff = i + 1;
}
}
else
break;
glBindTextures(0, i, textures);
if (lastdiff)
glBindTextures(0, lastdiff, &opengl_texture::units[0]);
}
else
{
@@ -1937,12 +1945,12 @@ void opengl_renderer::Render(TSubModel *Submodel)
// textures...
if (Submodel->m_material < 0)
{ // zmienialne skóry
Bind_Material(Submodel->ReplacableSkinId[-Submodel->m_material]);
Bind_Material(Submodel->ReplacableSkinId[-Submodel->m_material], Submodel);
}
else
{
// również 0
Bind_Material(Submodel->m_material);
Bind_Material(Submodel->m_material, Submodel);
}
// ...colors...
@@ -2106,7 +2114,7 @@ void opengl_renderer::Render(TSubModel *Submodel)
{
if (Global.fLuminance < Submodel->fLight)
{
Bind_Material(Submodel->m_material);
Bind_Material(Submodel->m_material, Submodel);
// main draw call
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
@@ -2781,11 +2789,11 @@ void opengl_renderer::Render_Alpha(TSubModel *Submodel)
// textures...
if (Submodel->m_material < 0)
{ // zmienialne skóry
Bind_Material(Submodel->ReplacableSkinId[-Submodel->m_material]);
Bind_Material(Submodel->ReplacableSkinId[-Submodel->m_material], Submodel);
}
else
{
Bind_Material(Submodel->m_material);
Bind_Material(Submodel->m_material, Submodel);
}
// ...luminance

View File

@@ -7,7 +7,5 @@ uniform sampler2D tex1;
void main()
{
//gl_FragColor = texture(tex, f_coord);
//gl_FragDepth = gl_FragCoord.z;
gl_FragDepth = gl_FragCoord.z + (1.0 - texture(tex1, f_coord).a);
}

View File

@@ -2,6 +2,8 @@
#include <common>
#param (color, 0, 0, 4, diffuse)
void main()
{
gl_FragColor = param[0];

View File

@@ -7,7 +7,11 @@ in vec4 f_light_pos;
#include <common>
#texture (tex1, 0, sRGB_A)
#param (color, 0, 0, 4, diffuse)
#param (diffuse, 1, 0, 1, one)
#param (specular, 1, 1, 1, specular)
#texture (diffuse, 0, sRGB_A)
uniform sampler2D tex1;
uniform sampler2DShadow shadowmap;
@@ -56,6 +60,7 @@ float calc_light(vec3 light_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 * param[1].y + diffuse_v * param[1].x;
return specular_v + diffuse_v;
}
@@ -113,7 +118,7 @@ void main()
if (i == 0U)
part *= shadow;
result += light.color * part * envcolor;
result += light.color * part;// * envcolor;
}
vec3 c = apply_fog(result * tex_color.xyz);

View File

@@ -0,0 +1 @@
#include <mat_colored.frag>

View File

@@ -0,0 +1 @@
#include <mat_default.frag>

View File

@@ -0,0 +1 @@
#include <mat_default.frag>

View File

@@ -1,123 +0,0 @@
#version 330
in vec3 f_normal;
in vec2 f_coord;
in vec3 f_pos;
in vec4 f_light_pos;
#include <common>
#texture (tex1, 0, sRGB_A)
uniform sampler2D tex1;
uniform sampler2DShadow shadowmap;
uniform samplerCube envmap;
float calc_shadow()
{
vec3 coords = f_light_pos.xyz / f_light_pos.w;
// do something better
float bias = 0.0001f;
//sampler PCF
//float shadow = texture(shadowmap, vec3(coords.xy, coords.z - bias));
//sampler PCF + PCF
float shadow = 0.0;
vec2 texel = 1.0 / textureSize(shadowmap, 0);
for (float y = -1.5; y <= 1.5; y += 1.0)
for (float x = -1.5; x <= 1.5; x += 1.0)
shadow += texture(shadowmap, coords.xyz + vec3(vec2(x, y) * texel, -bias));
shadow /= 16.0;
if (coords.z > 1.0f)
shadow = 1.0f;
return shadow;
}
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()
{
vec4 tex_color = texture(tex1, f_coord);
if (opacity == 0.0f && tex_color.a < 0.9f)
discard;
float shadow = calc_shadow();
vec3 result = ambient * 0.3 + vec3(1.0) * 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);
if (i == 0U)
part *= shadow;
result += light.color * part;
}
vec3 R = reflect(f_pos, normalize(f_normal));
vec3 r = texture(envmap, R).rgb;
r *= vec3(1.0, 0.84, 0.2);
vec3 c = apply_fog(result * tex_color.xyz);
gl_FragColor = vec4(c * 0.05 + r * 0.95, tex_color.w);
}

View File

@@ -2,11 +2,7 @@
in vec2 f_coord;
//uniform sampler2D tex;
void main()
{
//gl_FragColor = texture(tex, f_coord);
gl_FragDepth = gl_FragCoord.z;
//gl_FragDepth = gl_FragCoord.z + (1.0 - texture(tex, f_coord).w);
}