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)
{
vec4 color = texture(tex, tc);
vec4 color = texture(tex, tc) * pc;
if (color.a < 0.5)
{
discard;
}
FragColor = color * pc;
FragColor = color;
}

View File

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

View File

@ -10,8 +10,7 @@ out vec4 FragColor;
void main(void)
{
float billboard_alpha = mix(1.0, texture(tex, tc).a, billboard);
vec4 color = texture(tex, tc);
vec4 color = texture(tex, tc) * pc;
#if defined(Advanced_Lighting_Enabled)
vec2 xy = gl_FragCoord.xy / u_screen;
float FragZ = gl_FragCoord.z;
@ -19,9 +18,11 @@ void main(void)
float EnvZ = texture(dtex, xy).x;
vec4 EnvPos = getPosFromUVDepth(vec3(xy, EnvZ), u_inverse_projection_matrix);
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
float alpha = 1.0;
#endif
color = vec4(color.rgb * color.a, color.a);
FragColor = color * billboard_alpha * pc * alpha;
color = vec4(color.rgb * color.a * alpha, color.a * alpha);
FragColor = color;
}

View File

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

View File

@ -17,6 +17,7 @@
#include "graphics/cpu_particle_manager.hpp"
#include "graphics/sp/sp_base.hpp"
#include "graphics/stk_particle.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
@ -49,7 +50,7 @@ public:
/** A Shader to render alpha-test particles.
*/
class AlphaTestParticleRenderer : public TextureShader
<AlphaTestParticleRenderer, 1, int>
<AlphaTestParticleRenderer, 1, int, float>
{
public:
AlphaTestParticleRenderer()
@ -57,7 +58,7 @@ public:
loadProgram(PARTICLES_RENDERING,
GL_VERTEX_SHADER, "alphatest_particle.vert",
GL_FRAGMENT_SHADER, "alphatest_particle.frag");
assignUniforms("flips");
assignUniforms("flips", "billboard");
assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // AlphaTestParticleRenderer
}; // AlphaTestParticleRenderer
@ -95,6 +96,56 @@ void CPUParticleManager::addParticleNode(STKParticle* node)
m_particles_queue[tex_name].push_back(node);
} // 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;
// ----------------------------------------------------------------------------
@ -327,7 +378,8 @@ void CPUParticleManager::drawAll()
{
AlphaTestParticleRenderer::getInstance()->setTextureUnits
(cur_mat->getTexture()->getTextureHandler());
AlphaTestParticleRenderer::getInstance()->setUniforms(flips);
AlphaTestParticleRenderer::getInstance()->setUniforms(flips,
billboard);
}
glBindVertexArray(m_gl_particles.at(p.second)->m_vao);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4,

View File

@ -48,26 +48,9 @@ struct 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;
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];
}
const core::vector3df& color_to, float lf_time, float size);
// ------------------------------------------------------------------------
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);
}
CPUParticle(scene::IBillboardSceneNode* node);
};

View File

@ -523,10 +523,12 @@ void STKParticle::OnRegisterSceneNode()
m_particles_generating[i].m_size);
core::vector3df ret = m_color_from + (m_color_to - m_color_from) *
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.setBlue(core::clamp((int)(ret.Y * 255.0f), 0, 255));
p.color.setGreen(core::clamp((int)(ret.Z * 255.0f), 0, 255));
p.color.setAlpha(255);
p.color.setGreen(core::clamp((int)(ret.Y * 255.0f), 0, 255));
p.color.setBlue(core::clamp((int)(ret.Z * 255.0f), 0, 255));
p.color.setAlpha(core::clamp((int)(alpha * 255.0f), 0, 255));
Particles.push_back(p);
}
core::matrix4 inv(AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE);

View File

@ -29,6 +29,12 @@ using namespace irr;
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
{
private: