shader - Radial gradient - procedural texture for cocos2d-x v3.15+ -


in cocos2d-x there already layerradialgradient. works well, i've other shaders running on game scene, performance in problem now. it's using shader.

i want replace sprite generated radial gradient texture.

here example of layerradialgradient drawing result:

layerradialgradient::create(    color4b(179, 232, 184, 89),   color4b(0, 90, 128, 0),   620,   center,   0.0f); 

enter image description here

i've code suggestions like:

static color4b lerp(const color4b& value1, const color4b& value2, float amount) {     amount = clampf(amount, 0.0f, 1.0f);     return color4b(         (int)mathutil::lerp(value1.r, value2.r, amount),         (int)mathutil::lerp(value1.g, value2.g, amount),         (int)mathutil::lerp(value1.b, value2.b, amount),         (int)mathutil::lerp(value1.a, value2.a, amount)     ); }  static float falloff(float distance, float maxdistance, float scalingfactor) {     if (distance <= maxdistance / 3)     {         return scalingfactor * (1 - 3 * distance * distance / (maxdistance * maxdistance));     }     else if (distance <= maxdistance)     {         float x = 1 - distance / maxdistance;         return (3.f / 2.f) * scalingfactor * x * x;     }     else         return 0; }  static float falloff(float distance, float maxdistance) {     return falloff(distance, maxdistance, 1.f); }  static texture2d* generateradialgradienttexture(int size) {     auto radius = size / 2;     auto colors = new (std::nothrow) glubyte[size * size * 4];      color4b centercolor(color4b(179, 232, 184, 89));     color4b bordercolor(color4b(0, 90, 128, 0));              (int y = 0; y < size; y++)     {         (int x = 0; x < size; x++)         {             float distance = vec2::one.distance(vec2(x, y) / radius);             float alpha = falloff(distance, 1, 1);              int idx = (y * size + x) * 4;             float innergradient = falloff(distance, 0.6f, 0.8f);             auto color = lerp(bordercolor, centercolor, innergradient);              colors[idx + 0] = color.r;             colors[idx + 1] = color.g;             colors[idx + 2] = color.b;              //alpha             colors[idx + 3] = (glbyte)clampf(alpha * 256.f + 0.5f, 0.f, 255.f);         }     }      auto txt = new texture2d();     txt->initwithdata(colors, size * size * 4, texture2d::pixelformat::rgba8888, size, size, size(size, size));      delete[] colors;     return txt; } 

and use just:

sprite::createwithtexture(generateradialgradienttexture(radius)); 

but result different:

enter image description here

i investigated shader code of questions , developed similar algorithm in c++. algorithm linearly interpolates between 2 colors, starting @ center point, inner color, radially outwards outer color.
c++ algorithm generates texture size, specified input parameters:

#include <vector>  // std::vector #include <math.h>  // sqrt  texture2d * textureradialgradientcreate(     int            widht,     int            height,     const color4b &startcolor,     const color4b &endcolor,     float          radius,     const vec2    &center,     float          expand ) {     vec4 scol( startcolor.r / 255.0, startcolor.g / 255.0, startcolor.b / 255.0, startcolor.a / 255.0 );     vec4 ecol( endcolor.r / 255.0, endcolor.g / 255.0, endcolor.b / 255.0, endcolor.a / 255.0 );      std::vector<unsigned char> plane( widht * height * 4, 0 );     ( int y = 0; y < height; ++ y )     {         ( int x = 0; x < widht; ++ x )         {              float dx = x - center.x;              float dy = y - center.y;              float d = sqrt( dx*dx + dy*dy ) / radius;               vec4 mixcol( 0.0f, 0.0f, 0.0f, 0.0f );              if ( expand < 1.0f && d < 1.0f )              {                  float = ( d - expand ) / ( 1.0 - expand );                  mixcol = (d <= expand) ? scol : ( 1.0 - ) * scol + a*ecol;              }               size_t = ( y * widht + x ) * 4;              plane[i+0] = (unsigned char)(mixcol.x * 255.0f);              plane[i+1] = (unsigned char)(mixcol.y * 255.0f);              plane[i+2] = (unsigned char)(mixcol.z * 255.0f);              plane[i+3] = (unsigned char)(mixcol.w * 255.0f);         }     }      texture2d *texture = new texture2d();     if ( texture != nullptr )         texture->initwithdata( plane.data(), plane.size() / 4, texture2d::pixelformat::rgba8888, widht, height, cocos2d::size(widht, height) );     return texture; } 

e.g. quadratic texture wiht size of 600*600 , gradient highlight in center of texture:

int w = 600; int h = 600; float rad = ( w < h ? w : h ) / 2.0f; vec2 cpt( w / 2.0f, h / 2.0f ); texture = textureradialgradientcreate( w, h, layer_startcolor, layer_endcolor, rad, cpt, layer_expand ); 


extension answer

i don't know, maybe radial shader can optimized?

the conditional branches can avoided, using glsl clamp function, limiting interpolation parameter of mix function range (0, 1).
suggest optimize fragment shader this:

#ifdef gl_es varying lowp vec4 v_position; #else varying vec4 v_position;  #endif  uniform vec4 u_startcolor; uniform vec4 u_endcolor; uniform vec2 u_center; uniform float u_radius; uniform float u_expand;  void main() {     float d = distance(v_position.xy, u_center) / u_radius;     float = (d - u_expand) / (1.0 - u_expand);     gl_fragcolor = mix( u_startcolor, u_endcolor, clamp(0.0, 1.0, a) );  } 

Comments

Popular posts from this blog

angular - Ionic slides - dynamically add slides before and after -

minify - Minimizing css files -

Add a dynamic header in angular 2 http provider -