Why this shader doesn't work on Android?

73 views
Skip to first unread message

me2 beats

unread,
Jul 20, 2018, 5:05:36 AM7/20/18
to Kivy users support
below are 2 scripts
the first one just draws a circle, the second one draws an animated spinner
like this (see gif)

they both work on my ubuntu,
but the second one does not work on android (shows only the red window),
although the first one works


these programs differ only in the variable
spinner_shader

so I realized that the problem in the shader of the second script

what could be the reason for this?



from kivy.lang import Builder
from kivy.clock import Clock
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.core.window import Window
from kivy.graphics import RenderContext
from kivy.properties import StringProperty
from json import loads




KV
='''
FloatLayout:
    ShaderWidget:
        id: shader
        fs: app.fs



<ShaderWidget>:
    canvas:
        Color:
            rgb: 1, 0, 0
        Rectangle:
            pos: self.pos
            size: self.size
'''





spinner_shader
= '''

#ifdef GL_ES
precision highp float;
#endif

/* Outputs from the vertex shader */
varying vec4 frag_color;
varying vec2 tex_coord0;

/* uniform texture samplers */
uniform sampler2D texture0;


float radius = 20.;
vec2 center = vec2(100., 100.);

void main() {
  float distanceToCenter = distance(gl_FragCoord.xy, center);
  float inCircle = float(distanceToCenter < radius);
  gl_FragColor = vec4(inCircle);
}
'''






class ShaderWidget(FloatLayout):

    fs
= StringProperty(None)

   
def __init__(self, **kwargs):
       
# Instead of using Canvas, we will use a RenderContext,
       
# and change the default shader used.
       
self.canvas = RenderContext()

       
# call the constructor of parent
       
# if they are any graphics object, they will be added on our new canvas
       
super(ShaderWidget, self).__init__(**kwargs)

       
# We'll update our glsl variables in a clock
       
Clock.schedule_interval(self.update_glsl, 1 / 60.)

   
def on_fs(self, instance, value):
       
# set the fragment shader to our source code
        shader
= self.canvas.shader
        old_value
= shader.fs
        shader
.fs = value
       
if not shader.success:
            shader
.fs = old_value
           
print 'failure'


   
def update_glsl(self, *largs):
       
self.canvas['time'] = Clock.get_boottime()
       
self.canvas['resolution'] = list(map(float, self.size))
       
self.canvas['projection_mat'] = Window.render_context['projection_mat']



class SpinnerApp(App):
    fs
= StringProperty(spinner_shader)

   
def build(self):
       
self.root = Builder.load_string(KV)


if __name__ == '__main__':
   
SpinnerApp().run()



from kivy.lang import Builder
from kivy.clock import Clock
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.core.window import Window
from kivy.graphics import RenderContext
from kivy.properties import StringProperty
from json import loads




KV
='''
FloatLayout:
    ShaderWidget:
        id: shader
        fs: app.fs



<ShaderWidget>:
    canvas:
        Color:
            rgb: 1, 0, 0
        Rectangle:
            pos: self.pos
            size: self.size
'''





spinner_shader
= '''

#ifdef GL_ES
precision highp float;
precision mediump float;
#endif

/* Outputs from the vertex shader */
varying vec4 frag_color;
varying vec2 tex_coord0;

/* uniform texture samplers */
uniform sampler2D texture0;


uniform float time;
uniform vec2 resolution;

float PI = 3.14159;
vec2 center = resolution * 0.5;
float radius = min(resolution.x, resolution.y) * .5;

float circle(vec2 coord, vec2 center, float radius) {
  float distanceToCenter = distance(coord, center);
  return smoothstep(distanceToCenter - 2., distanceToCenter, radius);
}

bool isAngleBetween(float target, float angle1, float angle2) {
  float startAngle = min(angle1, angle2);
  float endAngle = max(angle1, angle2);

  if (endAngle - startAngle < 0.1) {
    return false;
  }

  target = mod((360. + (mod(target, 360.))), 360.);
  startAngle = mod((3600000. + startAngle), 360.);
  endAngle = mod((3600000. + endAngle), 360.);

  if (startAngle < endAngle) return startAngle <= target && target <= endAngle;
  return startAngle <= target || target <= endAngle;
}

float sector(vec2 coord, vec2 center, float startAngle, float endAngle) {
  vec2 uvToCenter = coord - center;
  float angle = degrees(atan(uvToCenter.y, uvToCenter.x));
  if (isAngleBetween(angle, startAngle, endAngle)) {
    return 1.0;
  } else {
    return 0.;
  }
}

float arc(vec2 uv, vec2 center, float startAngle, float endAngle, float innerRadius, float outerRadius) {
  float result = 0.0;
  result = sector(uv, center, startAngle, endAngle) * circle(uv, center, outerRadius) * (1.0 - circle(uv, center, innerRadius));
  return result;
}

vec4 rgb(float r, float g, float b) {
    return vec4(r / 255., g / 255., b / 255., 1.);
}

void main() {
  vec2 coord = vec2(gl_FragCoord);
  float outerRadius = min(resolution.x, resolution.y) * .5;

  vec4 backgroundColor = vec4(0.);
  float halfPI = PI * .5;
  float periodicTime = mod(time * .25, PI) - halfPI;
  vec4 color = rgb(255. * (sin(periodicTime) + 1.), 60. * .05 / 2., 160.) * (radius / distance(gl_FragCoord.xy, center));

  float innerRadius = outerRadius -6.;

  float startX = clamp(periodicTime, -halfPI, 0.);
  float endX = clamp(periodicTime, 0., halfPI);

  float angleVariation = sin(startX) + 1.;
  float endAngleVariation = sin(endX);
  float rotation = 180. * (sin(periodicTime) + 1.);

  float startAngle = 360. * angleVariation + rotation - 90.;
  float endAngle = 360. * endAngleVariation + rotation - 90.;

  float isFilled = arc(coord, center, - startAngle, - endAngle, innerRadius, outerRadius);
  gl_FragColor = (backgroundColor - (backgroundColor - color) * isFilled);
}
'''






class ShaderWidget(FloatLayout):

    fs
= StringProperty(None)

   
def __init__(self, **kwargs):
       
# Instead of using Canvas, we will use a RenderContext,
       
# and change the default shader used.
       
self.canvas = RenderContext()

       
# call the constructor of parent
       
# if they are any graphics object, they will be added on our new canvas
       
super(ShaderWidget, self).__init__(**kwargs)

       
# We'll update our glsl variables in a clock
       
Clock.schedule_interval(self.update_glsl, 1 / 60.)

   
def on_fs(self, instance, value):
       
# set the fragment shader to our source code
        shader
= self.canvas.shader
        old_value
= shader.fs
        shader
.fs = value
       
if not shader.success:
            shader
.fs = old_value
           
print 'failure'


   
def update_glsl(self, *largs):
       
self.canvas['time'] = Clock.get_boottime()
       
self.canvas['resolution'] = list(map(float, self.size))
       
self.canvas['projection_mat'] = Window.render_context['projection_mat']



class SpinnerApp(App):
    fs
= StringProperty(spinner_shader)

   
def build(self):
       
self.root = Builder.load_string(KV)


if __name__ == '__main__':
   
SpinnerApp().run()


christopher okoro

unread,
Jul 20, 2018, 5:15:58 AM7/20/18
to Kivy users support
If you compiled and it crashes, then it's probably because of your json import. U should look for an alternative because python for android doesn't have that module
Message has been deleted

me2 beats

unread,
Jul 20, 2018, 6:14:08 AM7/20/18
to Kivy users support
But why the first example work?
It doesn't use json?

PS I use Buildoser

qua non

unread,
Jul 20, 2018, 8:13:12 AM7/20/18
to kivy-...@googlegroups.com
Would you please post a log of the crash?
--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To post to this group, send email to kivy-...@googlegroups.com.
Visit this group at https://groups.google.com/group/kivy-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/1a52cb9b-c06d-4840-9b0a-8c665471dab1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

me2 beats

unread,
Jul 21, 2018, 9:28:16 AM7/21/18
to Kivy users support
Ok guys I found the cause of the problem, but it's strange for me.

it turns out that I can not specify variables outside functions (like the number pi) as follows:

#ifdef GL_ES
precision highp
float;
#endif


uniform vec2 resolution
;


vec2 center = resolution;
float radius = 300.;


void main() {

  vec4 color
= vec4(.5, .5, .5, 1.) * (radius / distance(gl_FragCoord.xy, center));

  gl_FragColor
= color;
}



But I can do it inside the main function

#ifdef GL_ES
precision highp float;
#endif

uniform vec2 resolution;


void main() {

  vec2 center = resolution;
  float radius = 300.;

  vec4 color = vec4(.5, .5, .5, 1.) * (radius / distance(gl_FragCoord.xy, center));

  gl_FragColor = color;
}




I'm far from C language, but it's strange for me at least because both shaders above work correctly on my ubuntu
Reply all
Reply to author
Forward
0 new messages