Use uniform rendering code for particle rendering

1. Remove pow in shader and do srgb conversion in code

2. Fix setGreen and setBlue order

3. Multiply particle color first like vertex color in the other shaders

4. Fix incorrect smoothstep
This commit is contained in:
Benau 2022-09-09 09:41:32 +08:00
parent 155b73d452
commit dcad21b830
8 changed files with 86 additions and 50 deletions

View File

@ -6,10 +6,10 @@ out vec4 FragColor;
void main(void) void main(void)
{ {
vec4 color = texture(tex, tc); vec4 color = texture(tex, tc) * pc;
if (color.a < 0.5) if (color.a < 0.5)
{ {
discard; discard;
} }
FragColor = color * pc; FragColor = color;
} }

View File

@ -1,4 +1,5 @@
uniform int flips; uniform int flips;
uniform float billboard;
#ifdef Explicit_Attrib_Location_Usable #ifdef Explicit_Attrib_Location_Usable
@ -35,14 +36,10 @@ void main(void)
return; return;
} }
float lifetime = color_lifetime.w; float lifetime = size.y;
vec4 particle_color = vec4(color_lifetime.zyx, 1.0); vec2 particle_size = mix(size.xx, size, billboard);
tc = Texcoord; tc = Texcoord;
pc = color_lifetime.zyxw;
#if !defined(Advanced_Lighting_Enabled)
particle_color.rgb = pow(particle_color.rgb, vec3(1.0 / 2.2));
#endif
pc = particle_color;
vec4 viewpos = vec4(0.); vec4 viewpos = vec4(0.);
if (flips == 1) if (flips == 1)
@ -51,7 +48,7 @@ void main(void)
float sin_a = sin(mod(angle / 2.0, 6.283185307179586)); float sin_a = sin(mod(angle / 2.0, 6.283185307179586));
float cos_a = cos(mod(angle / 2.0, 6.283185307179586)); float cos_a = cos(mod(angle / 2.0, 6.283185307179586));
vec4 quat = normalize(vec4(vec3(0.0, 1.0, 0.0) * sin_a, cos_a)); vec4 quat = normalize(vec4(vec3(0.0, 1.0, 0.0) * sin_a, cos_a));
vec3 newquadcorner = vec3(size * quadcorner, 0.0); vec3 newquadcorner = vec3(particle_size * quadcorner, 0.0);
newquadcorner = newquadcorner + 2.0 * cross(cross(newquadcorner, newquadcorner = newquadcorner + 2.0 * cross(cross(newquadcorner,
quat.xyz) + quat.w * newquadcorner, quat.xyz); quat.xyz) + quat.w * newquadcorner, quat.xyz);
viewpos = u_view_matrix * vec4(Position + newquadcorner, 1.0); viewpos = u_view_matrix * vec4(Position + newquadcorner, 1.0);
@ -59,7 +56,7 @@ void main(void)
else else
{ {
viewpos = u_view_matrix * vec4(Position, 1.0); viewpos = u_view_matrix * vec4(Position, 1.0);
viewpos += vec4(size * quadcorner, 0.0, 0.0); viewpos += vec4(particle_size * quadcorner, 0.0, 0.0);
} }
gl_Position = u_projection_matrix * viewpos; gl_Position = u_projection_matrix * viewpos;
} }

View File

@ -10,8 +10,7 @@ out vec4 FragColor;
void main(void) void main(void)
{ {
float billboard_alpha = mix(1.0, texture(tex, tc).a, billboard); vec4 color = texture(tex, tc) * pc;
vec4 color = texture(tex, tc);
#if defined(Advanced_Lighting_Enabled) #if defined(Advanced_Lighting_Enabled)
vec2 xy = gl_FragCoord.xy / u_screen; vec2 xy = gl_FragCoord.xy / u_screen;
float FragZ = gl_FragCoord.z; float FragZ = gl_FragCoord.z;
@ -19,9 +18,11 @@ void main(void)
float EnvZ = texture(dtex, xy).x; float EnvZ = texture(dtex, xy).x;
vec4 EnvPos = getPosFromUVDepth(vec3(xy, EnvZ), u_inverse_projection_matrix); vec4 EnvPos = getPosFromUVDepth(vec3(xy, EnvZ), u_inverse_projection_matrix);
float alpha = clamp((EnvPos.z - FragmentPos.z) * 0.3, 0., 1.); float alpha = clamp((EnvPos.z - FragmentPos.z) * 0.3, 0., 1.);
// TODO remove this later if possible when implementing GE
alpha = mix(alpha, texture(tex, tc).a, billboard);
#else #else
float alpha = 1.0; float alpha = 1.0;
#endif #endif
color = vec4(color.rgb * color.a, color.a); color = vec4(color.rgb * color.a * alpha, color.a * alpha);
FragColor = color * billboard_alpha * pc * alpha; FragColor = color;
} }

View File

@ -36,15 +36,10 @@ void main(void)
return; return;
} }
float lifetime = color_lifetime.w; float lifetime = size.y;
float alpha = mix(smoothstep(1.0, 0.8, lifetime), lifetime, billboard); vec2 particle_size = mix(size.xx, size, billboard);
vec4 particle_color = vec4(color_lifetime.zyx, 1.0) * alpha;
tc = Texcoord; tc = Texcoord;
pc = color_lifetime.zyxw;
#if !defined(Advanced_Lighting_Enabled)
particle_color.rgb = pow(particle_color.rgb, vec3(1.0 / 2.2));
#endif
pc = particle_color;
vec4 viewpos = vec4(0.); vec4 viewpos = vec4(0.);
if (flips == 1) if (flips == 1)
@ -53,7 +48,7 @@ void main(void)
float sin_a = sin(mod(angle / 2.0, 6.283185307179586)); float sin_a = sin(mod(angle / 2.0, 6.283185307179586));
float cos_a = cos(mod(angle / 2.0, 6.283185307179586)); float cos_a = cos(mod(angle / 2.0, 6.283185307179586));
vec4 quat = normalize(vec4(vec3(0.0, 1.0, 0.0) * sin_a, cos_a)); vec4 quat = normalize(vec4(vec3(0.0, 1.0, 0.0) * sin_a, cos_a));
vec3 newquadcorner = vec3(size * quadcorner, 0.0); vec3 newquadcorner = vec3(particle_size * quadcorner, 0.0);
newquadcorner = newquadcorner + 2.0 * cross(cross(newquadcorner, newquadcorner = newquadcorner + 2.0 * cross(cross(newquadcorner,
quat.xyz) + quat.w * newquadcorner, quat.xyz); quat.xyz) + quat.w * newquadcorner, quat.xyz);
viewpos = u_view_matrix * vec4(Position + newquadcorner, 1.0); viewpos = u_view_matrix * vec4(Position + newquadcorner, 1.0);
@ -61,7 +56,7 @@ void main(void)
else else
{ {
viewpos = u_view_matrix * vec4(Position, 1.0); viewpos = u_view_matrix * vec4(Position, 1.0);
viewpos += vec4(size * quadcorner, 0.0, 0.0); viewpos += vec4(particle_size * quadcorner, 0.0, 0.0);
} }
gl_Position = u_projection_matrix * viewpos; gl_Position = u_projection_matrix * viewpos;
} }

View File

@ -17,6 +17,7 @@
#include "graphics/cpu_particle_manager.hpp" #include "graphics/cpu_particle_manager.hpp"
#include "graphics/sp/sp_base.hpp"
#include "graphics/stk_particle.hpp" #include "graphics/stk_particle.hpp"
#include "graphics/irr_driver.hpp" #include "graphics/irr_driver.hpp"
#include "graphics/material.hpp" #include "graphics/material.hpp"
@ -49,7 +50,7 @@ public:
/** A Shader to render alpha-test particles. /** A Shader to render alpha-test particles.
*/ */
class AlphaTestParticleRenderer : public TextureShader class AlphaTestParticleRenderer : public TextureShader
<AlphaTestParticleRenderer, 1, int> <AlphaTestParticleRenderer, 1, int, float>
{ {
public: public:
AlphaTestParticleRenderer() AlphaTestParticleRenderer()
@ -57,7 +58,7 @@ public:
loadProgram(PARTICLES_RENDERING, loadProgram(PARTICLES_RENDERING,
GL_VERTEX_SHADER, "alphatest_particle.vert", GL_VERTEX_SHADER, "alphatest_particle.vert",
GL_FRAGMENT_SHADER, "alphatest_particle.frag"); GL_FRAGMENT_SHADER, "alphatest_particle.frag");
assignUniforms("flips"); assignUniforms("flips", "billboard");
assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // AlphaTestParticleRenderer } // AlphaTestParticleRenderer
}; // AlphaTestParticleRenderer }; // AlphaTestParticleRenderer
@ -95,6 +96,56 @@ void CPUParticleManager::addParticleNode(STKParticle* node)
m_particles_queue[tex_name].push_back(node); m_particles_queue[tex_name].push_back(node);
} // addParticleNode } // addParticleNode
// ============================================================================
CPUParticle::CPUParticle(const core::vector3df& position,
const core::vector3df& color_from,
const core::vector3df& color_to, float lf_time,
float size)
: m_position(position)
{
core::vector3df ret = color_from + (color_to - color_from) * lf_time;
float alpha = 1.0f - lf_time;
alpha = glslSmoothstep(0.0f, 0.35f, alpha);
int r = core::clamp((int)(ret.X * 255.0f), 0, 255);
int g = core::clamp((int)(ret.Y * 255.0f), 0, 255);
int b = core::clamp((int)(ret.Z * 255.0f), 0, 255);
if (CVS->isDeferredEnabled() && CVS->isGLSL())
{
using namespace SP;
r = srgb255ToLinear(r);
g = srgb255ToLinear(g);
b = srgb255ToLinear(b);
}
m_color_lifetime.setRed(r);
m_color_lifetime.setGreen(g);
m_color_lifetime.setBlue(b);
m_color_lifetime.setAlpha(core::clamp((int)(alpha * 255.0f), 0, 255));
if (size != 0.0f)
{
m_size[0] = MiniGLM::toFloat16(size);
m_size[1] = MiniGLM::toFloat16(lf_time);
}
else
memset(m_size, 0, sizeof(m_size));
} // CPUParticle
// ============================================================================
CPUParticle::CPUParticle(scene::IBillboardSceneNode* node)
{
m_position = node->getAbsolutePosition();
video::SColor unused_bottom;
node->getColor(m_color_lifetime, unused_bottom);
if (CVS->isDeferredEnabled() && CVS->isGLSL())
{
using namespace SP;
m_color_lifetime.setRed(srgb255ToLinear(m_color_lifetime.getRed()));
m_color_lifetime.setGreen(srgb255ToLinear(m_color_lifetime.getGreen()));
m_color_lifetime.setBlue(srgb255ToLinear(m_color_lifetime.getBlue()));
}
m_size[0] = MiniGLM::toFloat16(node->getSize().Width);
m_size[1] = MiniGLM::toFloat16(node->getSize().Height);
} // CPUParticle
// ============================================================================ // ============================================================================
GLuint CPUParticleManager::m_particle_quad = 0; GLuint CPUParticleManager::m_particle_quad = 0;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -327,7 +378,8 @@ void CPUParticleManager::drawAll()
{ {
AlphaTestParticleRenderer::getInstance()->setTextureUnits AlphaTestParticleRenderer::getInstance()->setTextureUnits
(cur_mat->getTexture()->getTextureHandler()); (cur_mat->getTexture()->getTextureHandler());
AlphaTestParticleRenderer::getInstance()->setUniforms(flips); AlphaTestParticleRenderer::getInstance()->setUniforms(flips,
billboard);
} }
glBindVertexArray(m_gl_particles.at(p.second)->m_vao); glBindVertexArray(m_gl_particles.at(p.second)->m_vao);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4,

View File

@ -48,26 +48,9 @@ struct CPUParticle
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
CPUParticle(const core::vector3df& position, CPUParticle(const core::vector3df& position,
const core::vector3df& color_from, const core::vector3df& color_from,
const core::vector3df& color_to, float lf_time, float size) const core::vector3df& color_to, float lf_time, float size);
: m_position(position)
{
core::vector3df ret = color_from + (color_to - color_from) * lf_time;
m_color_lifetime.setRed(core::clamp((int)(ret.X * 255.0f), 0, 255));
m_color_lifetime.setBlue(core::clamp((int)(ret.Y * 255.0f), 0, 255));
m_color_lifetime.setGreen(core::clamp((int)(ret.Z * 255.0f), 0, 255));
m_color_lifetime.setAlpha(core::clamp((int)(lf_time * 255.0f), 0, 255));
m_size[0] = MiniGLM::toFloat16(size);
m_size[1] = m_size[0];
}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
CPUParticle(scene::IBillboardSceneNode* node) CPUParticle(scene::IBillboardSceneNode* node);
{
m_position = node->getAbsolutePosition();
video::SColor unused_bottom;
node->getColor(m_color_lifetime, unused_bottom);
m_size[0] = MiniGLM::toFloat16(node->getSize().Width);
m_size[1] = MiniGLM::toFloat16(node->getSize().Height);
}
}; };

View File

@ -523,10 +523,12 @@ void STKParticle::OnRegisterSceneNode()
m_particles_generating[i].m_size); m_particles_generating[i].m_size);
core::vector3df ret = m_color_from + (m_color_to - m_color_from) * core::vector3df ret = m_color_from + (m_color_to - m_color_from) *
m_particles_generating[i].m_lifetime; m_particles_generating[i].m_lifetime;
float alpha = 1.0f - m_particles_generating[i].m_lifetime;
alpha = glslSmoothstep(0.0f, 0.35f, alpha);
p.color.setRed(core::clamp((int)(ret.X * 255.0f), 0, 255)); p.color.setRed(core::clamp((int)(ret.X * 255.0f), 0, 255));
p.color.setBlue(core::clamp((int)(ret.Y * 255.0f), 0, 255)); p.color.setGreen(core::clamp((int)(ret.Y * 255.0f), 0, 255));
p.color.setGreen(core::clamp((int)(ret.Z * 255.0f), 0, 255)); p.color.setBlue(core::clamp((int)(ret.Z * 255.0f), 0, 255));
p.color.setAlpha(255); p.color.setAlpha(core::clamp((int)(alpha * 255.0f), 0, 255));
Particles.push_back(p); Particles.push_back(p);
} }
core::matrix4 inv(AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE); core::matrix4 inv(AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE);

View File

@ -29,6 +29,12 @@ using namespace irr;
struct CPUParticle; struct CPUParticle;
inline float glslSmoothstep(float edge0, float edge1, float x)
{
float t = core::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
return t * t * (3.0f - 2.0f * t);
}
class STKParticle : public scene::CParticleSystemSceneNode class STKParticle : public scene::CParticleSystemSceneNode
{ {
private: private: