Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Shader affects wrong model — Gideros Forum

Shader affects wrong model

YanYan Member
edited February 2017 in Bugs and issues
Heres my code, it produces two shapes, textured with some 2px x 2px texture. Ive aplied simple shader on this shapes, providing some INT flag, 1 - red color, 2 - blue color. According this shapes having different flags, given to shader, they should have different colors, but the last shader like overlaps all shapes textures. So if you comment 2nd shape, the first will have a true color, but if not ull get just one color for all shapes, why this happens and why shader affects not only shape area texture, but like all the screen. Test project attached.
BlurEffect={}
 
BlurEffect.VS_GL=[[
uniform highp mat4 vMatrix;
uniform highp mat4 vWMatrix;
 
attribute highp vec3 vVertex;
attribute mediump vec2 vTexCoord;
 
varying mediump vec2 fTexCoord;
varying mediump vec4 fWorldCoord;
 
void main() {
  vec4 vertex = vec4(vVertex,1.0);
  gl_Position = vMatrix*vertex;
  fTexCoord = vTexCoord;
  fWorldCoord = vWMatrix*vertex;
}
]]
 
BlurEffect.FS_GL=[[
#ifdef GL_ES
  precision mediump float;
#endif
 
const float pi = 3.14159;
 
uniform lowp vec4 fColor;
uniform mediump vec4 fTexSize;
uniform lowp sampler2D fTexture;
 
uniform lowp int myColor;
 
varying mediump vec2 fTexCoord;
varying mediump vec4 fWorldCoord;
 
void main()
{	
	float red = 0;
	float blue = 0;
 
	if (myColor == 1) {
		red = 0.5;
	}
 
	if (myColor == 2) {
		blue = 0.5;
	}
 
	vec4 solidRed		= vec4(red,0,blue,1);
 
    gl_FragColor = solidRed;
}
]]
 
BlurEffect.Shader=Shader.new(BlurEffect.VS_GL,BlurEffect.FS_GL,Shader.FLAG_FROM_CODE, {
	{name="vMatrix",type=Shader.CMATRIX,sys=Shader.SYS_WVP,vertex=true},
	{name="vWMatrix",type=Shader.CMATRIX,sys=Shader.SYS_WORLD,vertex=true},
	{name="fTexture",type=Shader.CTEXTURE,vertex=false},
	{name="fTexSize",type=Shader.CFLOAT4,sys=Shader.SYS_TEXTUREINFO,vertex=false},
	{name="fColor",type=Shader.CFLOAT4,sys=Shader.SYS_COLOR,vertex=false},
	{name="myColor",type=Shader.CINT,vertex=false},
},
{
	{name="vVertex",type=Shader.DFLOAT,mult=3,slot=0,offset=0},
	{name="vColor",type=Shader.DUBYTE,mult=4,slot=1,offset=0},
	{name="vTexCoord",type=Shader.DFLOAT,mult=2,slot=2,offset=0},
});
 
local texture = Texture.new("pixel.jpg", true) --2x2 green pixel
 
local shape1 = Shape.new()
shape1:setFillStyle(Shape.TEXTURE, texture)
shape1:beginPath()
shape1:lineTo(50, 100)
shape1:lineTo(450, 100)
shape1:lineTo(450, 500)
shape1:lineTo(50, 500)
shape1:lineTo(50, 100)
shape1:closePath()
shape1:endPath()
 
BlurEffect.Shader:setConstant("myColor", Shader.CINT, 1, 1)
 
shape1:setShader(BlurEffect.Shader)
 
stage:addChild(shape1)
 
-- If you comment from here, first shape will have "true" color, but if not, the last shape shader will redraw also on first shape
 
local shape2 = Shape.new()
shape2:setFillStyle(Shape.TEXTURE, texture)
shape2:beginPath()
shape2:lineTo(600, 100)
shape2:lineTo(900, 100)
shape2:lineTo(900, 500)
shape2:lineTo(500, 500)
shape2:lineTo(500, 100)
shape2:closePath()
shape2:endPath()
 
BlurEffect.Shader:setConstant("myColor", Shader.CINT, 1, 2)
 
shape2:setShader(BlurEffect.Shader)
 
stage:addChild(shape2)
vk.com/yan_alex

Comments

  • hgy29hgy29 Maintainer
    hi @yan,
    change
    BlurEffect.Shader:setConstant("myColor", Shader.CINT, 1, 2)
    to
    shapeX:setShaderConstant("myColor", Shader.CINT, 1, 2)
  • YanYan Member
    edited February 2017
    hi @yan,
    change
    BlurEffect.Shader:setConstant("myColor", Shader.CINT, 1, 2)
    to
    shapeX:setShaderConstant("myColor", Shader.CINT, 1, 2)
    Great,that works BUT we should define setShader before setShaderConstant ! Can you explain, why this happens ? Shader needs some time to precompile ? Because I found another behavior is strange, when I put shader definition in to some loop it gives me error.
    vk.com/yan_alex
  • hgy29hgy29 Maintainer
    Accepted Answer
    Well shader compilation takes some time, but this is done synchronously, so it should work even in a loop. You may be limited by how many shaders the GPU support at the same time however.

    About shader:setConstant() vs sprite:setShaderConstant(), the former sets a uniform value directly in the shader program, while the latter instruct gideros to set the uniform right before actually using the shader. The second form is more suitable to customize shader behavior sprite by sprite, while the first can be used to set global behavior for all sprites using the shader.

    And yes, you should setShader() before setShaderConstant(), so that gideros can check the constant you gave vs what the shader expects. Removing or changing the shader for the sprite also clears any setShaderConstant() issued beforehand.

    Does this make sense ?
  • Yes, totally explains all the cases! Great thanks for education! Unfortunately theres no source to read about such tiny places, so unfortunately I cant figure out It by myself.

    P.S. I didnt found setShaderConstant in Gideros reference - think should be fixed, who should be noticed about this ?
    vk.com/yan_alex
  • Heres one another problem in build 2018.10

    If shader is not set it would been taking value from other sprite !!! Even if you use setShaderConstant !!!

    Attched test case project
    zip
    zip
    SHADER TEST.zip
    3K
    vk.com/yan_alex
  • hgy29hgy29 Maintainer
    Yes, children sprites are technically enclosed in the drawing process of parent sprite, so all attributes set to the parent Sprite are somehow applied to children, such as colorTransform, clip, etc. The way it is done now, the same goes for Shader args, and even worse since shader constants aren't reset to previous value when Sprite drawing has ended, so whatever has been set is still valid for subsequent draws unless overriden.
  • YanYan Member
    edited December 2018
    hgy29 said:

    Yes, children sprites are technically enclosed in the drawing process of parent sprite, so all attributes set to the parent Sprite are somehow applied to children, such as colorTransform, clip, etc. The way it is done now, the same goes for Shader args, and even worse since shader constants aren't reset to previous value when Sprite drawing has ended, so whatever has been set is still valid for subsequent draws unless overriden.

    Well if you look at testcase, you should notice that shader applied to different sprites that are only siblings of parent stage, and they not inheited from themselves.

    So if shaderConstant set to one of sprites this constant used for other shaders that not yet has setted constant.

    Ive solved this by forcing constant value to each sprite after I do setShader to this sprite.
    vk.com/yan_alex
  • hgy29hgy29 Maintainer
    yes, true, I didn't realise they were siblings in your example, but you got it now: shader constant is in fact a variable of the shader program itself, so its value is retained as long as no setConstant/setShaderConstant is issued.
Sign In or Register to comment.