Add colorization for vulkan

This commit is contained in:
Benau 2022-09-11 11:05:33 +08:00
parent d3ddcd884d
commit 76c39afd8b
16 changed files with 155 additions and 95 deletions

View File

@ -1,15 +1,27 @@
layout(location = 0) in vec4 f_vertex_color;
layout(location = 1) in vec2 f_uv;
layout(location = 3) flat in int f_material_id;
layout(location = 4) in float f_hue_change;
layout(location = 0) out vec4 o_color;
#include "utils/sample_mesh_texture.h"
#include "../utils/rgb_conversion.frag"
void main()
{
vec4 mixed_color = sampleMeshTexture0(f_material_id, f_uv)* f_vertex_color;
if (mixed_color.a < 0.5)
vec4 tex_color = sampleMeshTexture0(f_material_id, f_uv);
if (tex_color.a * f_vertex_color.a < 0.5)
discard;
o_color = vec4(mixed_color.xyz, 1.0);
tex_color.xyz *= f_vertex_color.xyz;
if (f_hue_change > 0.0)
{
vec3 old_hsv = rgbToHsv(tex_color.rgb);
vec2 new_xy = vec2(f_hue_change, old_hsv.y);
vec3 new_color = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z));
tex_color = vec4(new_color.r, new_color.g, new_color.b, tex_color.a);
}
o_color = vec4(tex_color.xyz, 1.0);
}

View File

@ -1,13 +1,34 @@
layout(location = 0) in vec4 f_vertex_color;
layout(location = 1) in vec2 f_uv;
layout(location = 3) flat in int f_material_id;
layout(location = 4) in float f_hue_change;
layout(location = 0) out vec4 o_color;
#include "utils/sample_mesh_texture.h"
#include "../utils/rgb_conversion.frag"
void main()
{
vec3 mixed_color = sampleMeshTexture0(f_material_id, f_uv).xyz * f_vertex_color.xyz;
vec4 tex_color = sampleMeshTexture0(f_material_id, f_uv);
if (f_hue_change > 0.0)
{
float mask = tex_color.a;
vec3 old_hsv = rgbToHsv(tex_color.rgb);
float mask_step = step(mask, 0.5);
#ifndef PBR_ENABLED
// For similar color
float saturation = mask * 1.825; // 2.5 * 0.5 ^ (1. / 2.2)
#else
float saturation = mask * 2.5;
#endif
vec2 new_xy = mix(vec2(old_hsv.x, old_hsv.y), vec2(f_hue_change,
max(old_hsv.y, saturation)), vec2(mask_step, mask_step));
vec3 new_color = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z));
tex_color = vec4(new_color.r, new_color.g, new_color.b, 1.0);
}
vec3 mixed_color = tex_color.xyz * f_vertex_color.xyz;
o_color = vec4(mixed_color * 0.5, 0.5);
}

View File

@ -12,7 +12,7 @@ void main()
offset += vec3(cos(u_push_constants.m_wind_direction) * 0.7);
vec4 v_world_position = getWorldPosition(
u_object_buffer.m_objects[gl_InstanceIndex].m_position.xyz + offset *
u_object_buffer.m_objects[gl_InstanceIndex].m_translation + offset *
v_color.r,
u_object_buffer.m_objects[gl_InstanceIndex].m_rotation,
u_object_buffer.m_objects[gl_InstanceIndex].m_scale.xyz, v_position);
@ -21,4 +21,5 @@ void main()
f_uv = v_uv;
f_uv_two = v_uv_two;
f_material_id = u_object_buffer.m_objects[gl_InstanceIndex].m_material_id;
f_hue_change = u_object_buffer.m_objects[gl_InstanceIndex].m_hue_change;
}

View File

@ -1,13 +1,34 @@
layout(location = 0) in vec4 f_vertex_color;
layout(location = 1) in vec2 f_uv;
layout(location = 3) flat in int f_material_id;
layout(location = 4) in float f_hue_change;
layout(location = 0) out vec4 o_color;
#include "utils/sample_mesh_texture.h"
#include "../utils/rgb_conversion.frag"
void main()
{
vec3 mixed_color = sampleMeshTexture0(f_material_id, f_uv).xyz * f_vertex_color.xyz;
vec4 tex_color = sampleMeshTexture0(f_material_id, f_uv);
if (f_hue_change > 0.0)
{
float mask = tex_color.a;
vec3 old_hsv = rgbToHsv(tex_color.rgb);
float mask_step = step(mask, 0.5);
#ifndef PBR_ENABLED
// For similar color
float saturation = mask * 1.825; // 2.5 * 0.5 ^ (1. / 2.2)
#else
float saturation = mask * 2.5;
#endif
vec2 new_xy = mix(vec2(old_hsv.x, old_hsv.y), vec2(f_hue_change,
max(old_hsv.y, saturation)), vec2(mask_step, mask_step));
vec3 new_color = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z));
tex_color = vec4(new_color.r, new_color.g, new_color.b, 1.0);
}
vec3 mixed_color = tex_color.xyz * f_vertex_color.xyz;
o_color = vec4(mixed_color, 1.0);
}

View File

@ -4,7 +4,7 @@
void main()
{
vec4 v_world_position = getWorldPosition(
u_object_buffer.m_objects[gl_InstanceIndex].m_position.xyz,
u_object_buffer.m_objects[gl_InstanceIndex].m_translation,
u_object_buffer.m_objects[gl_InstanceIndex].m_rotation,
u_object_buffer.m_objects[gl_InstanceIndex].m_scale.xyz, v_position);
gl_Position = u_camera.m_projection_view_matrix * v_world_position;
@ -12,4 +12,5 @@ void main()
f_uv = v_uv + u_object_buffer.m_objects[gl_InstanceIndex].m_texture_trans;
f_uv_two = v_uv_two;
f_material_id = u_object_buffer.m_objects[gl_InstanceIndex].m_material_id;
f_hue_change = u_object_buffer.m_objects[gl_InstanceIndex].m_hue_change;
}

View File

@ -9,9 +9,9 @@ void main()
v_weight[1] * u_skinning_matrices.m_mat[max(v_joint[1] + offset, 0)] +
v_weight[2] * u_skinning_matrices.m_mat[max(v_joint[2] + offset, 0)] +
v_weight[3] * u_skinning_matrices.m_mat[max(v_joint[3] + offset, 0)];
vec4 v_skinning_position = joint_matrix * vec4(v_position.xyz, 1.0);
vec4 v_skinning_position = joint_matrix * vec4(v_position, 1.0);
vec4 v_world_position = getWorldPosition(
u_object_buffer.m_objects[gl_InstanceIndex].m_position.xyz,
u_object_buffer.m_objects[gl_InstanceIndex].m_translation,
u_object_buffer.m_objects[gl_InstanceIndex].m_rotation,
u_object_buffer.m_objects[gl_InstanceIndex].m_scale.xyz,
v_skinning_position.xyz);
@ -20,4 +20,5 @@ void main()
f_uv = v_uv + u_object_buffer.m_objects[gl_InstanceIndex].m_texture_trans;
f_uv_two = v_uv_two;
f_material_id = u_object_buffer.m_objects[gl_InstanceIndex].m_material_id;
f_hue_change = u_object_buffer.m_objects[gl_InstanceIndex].m_hue_change;
}

View File

@ -10,7 +10,8 @@ layout(std140, set = 1, binding = 0) uniform CameraBuffer
struct ObjectData
{
vec4 m_position;
vec3 m_translation;
float m_hue_change;
vec4 m_rotation;
vec4 m_scale;
int m_skinning_offest;
@ -41,3 +42,4 @@ layout(location = 0) out vec4 f_vertex_color;
layout(location = 1) out vec2 f_uv;
layout(location = 2) out vec2 f_uv_two;
layout(location = 3) flat out int f_material_id;
layout(location = 4) out float f_hue_change;

View File

@ -30,7 +30,7 @@ ObjectData::ObjectData(irr::scene::ISceneNode* node, int material_id,
{
using namespace MiniGLM;
const irr::core::matrix4& model_mat = node->getAbsoluteTransformation();
float position[3] = { model_mat[12], model_mat[13], model_mat[14] };
float translation[3] = { model_mat[12], model_mat[13], model_mat[14] };
irr::core::quaternion rotation(0.0f, 0.0f, 0.0f, 1.0f);
irr::core::vector3df scale = model_mat.getScale();
if (scale.X != 0.0f && scale.Y != 0.0f && scale.Z != 0.0f)
@ -49,7 +49,7 @@ ObjectData::ObjectData(irr::scene::ISceneNode* node, int material_id,
// Conjugated quaternion in glsl
rotation.W = -rotation.W;
}
memcpy(m_position, position, sizeof(position));
memcpy(&m_translation_x, translation, sizeof(translation));
memcpy(m_rotation, &rotation, sizeof(irr::core::quaternion));
memcpy(m_scale, &scale, sizeof(irr::core::vector3df));
m_skinning_offset = skinning_offset;
@ -58,6 +58,11 @@ ObjectData::ObjectData(irr::scene::ISceneNode* node, int material_id,
node->getMaterial(irrlicht_material_id).getTextureMatrix(0);
m_texture_trans[0] = texture_matrix[8];
m_texture_trans[1] = texture_matrix[9];
auto& ri = node->getMaterial(irrlicht_material_id).getRenderInfo();
if (ri && ri->getHue() > 0.0f)
m_hue_change = ri->getHue();
else
m_hue_change = 0.0f;
} // ObjectData
// ----------------------------------------------------------------------------

View File

@ -28,7 +28,10 @@ class GEVulkanTextureDescriptor;
struct ObjectData
{
float m_position[4];
float m_translation_x;
float m_translation_y;
float m_translation_z;
float m_hue_change;
float m_rotation[4];
float m_scale[4];
int m_skinning_offset;

View File

@ -500,4 +500,9 @@ bool CentralVideoSettings::isARBTextureBufferObjectUsable() const
return hasTextureBufferObject;
}
bool CentralVideoSettings::supportsColorization() const
{
return isGLSL() || GE::getDriver()->getDriverType() == video::EDT_VULKAN;
}
#endif // !SERVER_ONLY

View File

@ -93,6 +93,7 @@ public:
bool isShadowEnabled() const;
bool isTextureCompressionEnabled() const;
bool isDeferredEnabled() const;
bool supportsColorization() const;
};
extern CentralVideoSettings* CVS;

View File

@ -259,11 +259,6 @@ void LODNode::add(int level, scene::ISceneNode* node, bool reparent)
m_nodes_set.insert(node);
node->setParent(this);
if (node->getType() == scene::ESNT_ANIMATED_MESH)
((scene::IAnimatedMeshSceneNode *) node)->setReadOnlyMaterials(true);
if (node->getType() == scene::ESNT_MESH)
((scene::IMeshSceneNode *) node)->setReadOnlyMaterials(true);
node->drop();
node->updateAbsolutePosition();

View File

@ -593,22 +593,25 @@ bool KartModel::loadModels(const KartProperties &kart_properties)
Vec3 kart_max = m_mesh->getMax();
#ifndef SERVER_ONLY
// Test if kart model support colorization
if (CVS->isGLSL())
{
for (u32 i = 0; i < m_mesh->getMeshBufferCount(); i++)
{
SP::SPMeshBuffer* mb =
static_cast<SP::SPMeshBuffer*>(m_mesh->getMeshBuffer(i));
SP::SPMeshBuffer* spmb =
dynamic_cast<SP::SPMeshBuffer*>(m_mesh->getMeshBuffer(i));
if (!spmb)
{
m_support_colorization = m_support_colorization ||
m_mesh->getMeshBuffer(i)->getMaterial().isColorizable();
continue;
}
// Pre-upload gl meshes and textures for kart screen
mb->uploadGLMesh();
std::vector<Material*> mbs = mb->getAllSTKMaterials();
spmb->uploadGLMesh();
std::vector<Material*> mbs = spmb->getAllSTKMaterials();
for (Material* m : mbs)
{
m_support_colorization =
m_support_colorization || m->isColorizable();
}
}
}
#endif
#undef MOVE_KART_MESHES

View File

@ -322,7 +322,7 @@ void World::initTeamArrows(AbstractKart* k)
KartModel* km = k->getKartModel();
// Color of karts can be changed using shaders if the model supports
if (km->supportColorization() && CVS->isGLSL())
if (km->supportColorization() && CVS->supportsColorization())
return;
float arrow_pos_height = km->getHeight() + 0.5f;

View File

@ -113,7 +113,7 @@ void BaseUserScreen::init()
{
#ifndef SERVER_ONLY
getWidget<IconButtonWidget>("default_kart_color")
->setVisible(CVS->isGLSL());
->setVisible(CVS->supportsColorization());
#endif
m_password_tb->setPasswordBox(true, L'*');

View File

@ -24,7 +24,6 @@
#include "graphics/lod_node.hpp"
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"
#include <ge_render_info.hpp>
#include "graphics/sp/sp_mesh_buffer.hpp"
#include "graphics/sp/sp_mesh_node.hpp"
#include "io/file_manager.hpp"
@ -41,6 +40,7 @@
#include <IAnimatedMeshSceneNode.h>
#include <ISceneManager.h>
#include <ge_render_info.hpp>
/** A track object: any additional object on the track. This object implements
* a graphics-only representation, i.e. there is no physical representation.
@ -196,35 +196,10 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
std::string model_name;
xml_node.get("model", &model_name);
#ifndef SERVER_ONLY
if (CVS->isGLSL())
{
scene::IMesh* mesh = NULL;
// Use the first material in mesh to determine hue
Material* colorized = NULL;
if (model_name.size() > 0)
{
mesh = irr_driver->getMesh(model_name);
if (mesh != NULL)
{
for (u32 j = 0; j < mesh->getMeshBufferCount(); j++)
{
SP::SPMeshBuffer* mb = static_cast<SP::SPMeshBuffer*>
(mesh->getMeshBuffer(j));
std::vector<Material*> mbs = mb->getAllSTKMaterials();
for (Material* m : mbs)
{
if (m->isColorizable() && m->hasRandomHue())
{
colorized = m;
break;
}
}
if (colorized != NULL)
{
break;
}
}
}
}
else
{
@ -232,12 +207,27 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
xml_node.get("lod_group", &group_name);
// Try to get the first mesh from lod groups
mesh = model_def_loader.getFirstMeshFor(group_name);
}
// Use the first material in mesh to determine hue
Material* colorized = NULL;
if (mesh != NULL)
{
for (u32 j = 0; j < mesh->getMeshBufferCount(); j++)
{
SP::SPMeshBuffer* mb = static_cast<SP::SPMeshBuffer*>
(mesh->getMeshBuffer(j));
scene::IMeshBuffer* buf = mesh->getMeshBuffer(j);
SP::SPMeshBuffer* mb = dynamic_cast<SP::SPMeshBuffer*>(buf);
if (!mb)
{
Material* m = material_manager->getMaterialFor(buf
->getMaterial().getTexture(0), buf);
if (m->isColorizable() && m->hasRandomHue())
{
colorized = m;
break;
}
continue;
}
std::vector<Material*> mbs = mb->getAllSTKMaterials();
for (Material* m : mbs)
{
@ -253,7 +243,6 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
}
}
}
}
// If at least one material is colorizable, add RenderInfo for it
if (colorized != NULL)
@ -264,7 +253,7 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
m_render_info = std::make_shared<GE::GERenderInfo>(hue);
}
}
}
#endif
scene::ISceneNode *glownode = NULL;
bool is_movable = false;