Basic Shader Help

Hi,
I’m tryin to execute a basic shader, but applying shader on the object makes it disappear. I have pasted the code below, Can anyone help me point out whats wrong in the code?

CODE:

Sprite * ball1 = Sprite::create(filename.png);
	_gameContainer->addChild(ball1);
	ball1->setPosition(100.f, 100.f);	
	shaderProgram = GLProgram::createWithFilenames("shaders/vertex.vsh", "shaders/pixel.fsh");
	shaderProgram->link();
	shaderProgram->updateUniforms();
	shaderProgram->retain();
	shaderProgram->addAttribute(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION);
	shaderProgram->addAttribute(GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::VERTEX_ATTRIB_COLOR);
	shaderProgram->addAttribute(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORD);
	ball1->setGLProgram(shaderProgram);

#vertex.vsh

attribute vec4 a_position;
attribute vec2 a_texCoord;
 
uniform mat4 u_MVPMatrix;
 
ifdef GL_ES
varying mediump vec2 v_texCoord;
else
varying vec2 v_texCoord;
endif
 
void main()
{

  gl_Position = u_MVPMatrix * a_position;
  v_texCoord = a_texCoord;
}

#pixel.fsh

ifdef GL_ES
precision mediump float;
endif
 
varying vec2 v_texCoord;

uniform sampler2D u_texture;
 
void main()
{
  gl_FragColor =  vec4(1.0,1.0,1.0,1.0);//texture2D(u_texture, v_texCoord);
}

All helps are highly appreciated…

1 Like

You might need to take a look at the built-in shader of Sprite class.
It uses SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP shader.

attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;

\n#ifdef GL_ES\n
varying lowp vec4 v_fragmentColor;
varying mediump vec2 v_texCoord;
\n#else\n
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
\n#endif\n

void main()
{
    gl_Position = CC_PMatrix * a_position;
    v_fragmentColor = a_color;
    v_texCoord = a_texCoord;
}

It uses CC_PMatrix not u_MVPMatrix. So I guess your problem is related to the transform part of your vertex shader code.

i’m using cocos2dx 3.2, anyway i will check late in the evening and update

changing to CC_MVPMatrix works!!! Thanks a lot.

Can u suggest some good tutorial or books for opengles shader(for a beginner).? I cant visualize things without understanding the flow of shaders.

Thanks

Here are a few good links to learn modern OpenGL programming.

thanks for the links :smile:

Hi all,
I have problem with a basic light shader

here is my vertex shader

attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;

uniform vec4 u_lightPosition;
uniform float divider;

varying lowp vec4 v_fragmentColor;
varying lowp vec2 v_texCoord;

void main()
{
    gl_Position = CC_MVPMatrix * a_position;
   //u_lightPosition == center of screen
   mediump float lightDist = distance(a_position, u_lightPosition);
 
    lightDist = lightDist/576.0;
    lightDist = 1.0 - lightDist;
    
    v_fragmentColor = vec4(1.0*lightDist, 1.0*lightDist, 1.0*lightDist, lightDist);
    v_texCoord = a_texCoord;
}

Pixel Shader

varying lowp vec4 v_fragmentColor;
varying lowp vec2 v_texCoord;

void main()
{
    // sample texture
    lowp vec4 fragColor = texture2D(CC_Texture0, v_texCoord);
    
    // set the color to fragment tint color * native fragment color
    gl_FragColor = vec4((fragColor.rgb*v_fragmentColor.rgb), v_fragmentColor.a);
}
---------------------------------------------------------------------------------------------

here is the output

From my understandings what i’m doing is calculating the color value at each vertices using the calculated light distance (distance between vertex position and light position(center of screen)) . i’m applying this shader on a solid orange color sprite whose size == screen_size.

my question is why the effect applies to only one vertex, and not all the vertices. i know fundamentally somethiing wrong in my code, kindly help me fix and make me understand.

It would be of great help if someone point me to a link that shows how to debug shaders (atleast a print statement either on mac-64bit or windows-32bit).

All helps are highly appreciated.

i managed to solve the above issue. Now i’m encountering some performance issue after updating an uniform variable every frame in pixel shader. Also the shader is applied on a full screen sized RenderTexture.

What would be the best place to render RenderTexture ? inside visit function or scheduled udpate?

Is it a good practice to update uniform variables every frame in pixel shader or not?

If not how to pass variables every frame to pixel shader?

All helps are highly appreciated !!!

some more info

actually i’m running a pixel shader on a full screen size image (960x640 RenderedToTexture), i have distance calculation as well that eats up most of the fps. i could see this by commenting out the distance calculation

without shader FPS - 60
With shader FPS - 15

i have pasted my code here plz have a look and let me know whats wrong in this code

precision mediump float;

struct Light
{
vec3 position;
vec3 color;
float intensity;
int active;
};

uniform Light lights[5];

varying mediump vec2 v_texCoord;
uniform float u_lightInnerFallOff;
uniform vec2 u_resolution;
uniform float u_fragAlpha;

void main()
{
    vec4 fragColor = texture2D(CC_Texture0, v_texCoord);
    vec3 v_fragmentIntensity = fragColor.rgb;
    float fragAlpha = u_fragAlpha;
    for (int index = 0; index < 5; index++)
    {
        if (lights[index].active == 1)
	{
    		mediump float lightDist = distance(vec3((v_texCoord * u_resolution), 0.0), lights[index].position);
		 
    		lowp float lightValue;

		if (lightDist < u_lightInnerFallOff)
		{
			lightValue = 1.0;
			v_fragmentIntensity = lights[index].color * vec3(1.0, 1.0, 1.0);
		}
		else
		{
			lightValue = u_lightInnerFallOff/lightDist;
			v_fragmentIntensity = lights[index].color * v_fragmentIntensity;
		}
		fragAlpha = fragAlpha + (lightValue * lights[index].intensity);
	}
}
gl_FragColor = vec4(v_fragmentIntensity, fragAlpha);
}

Things i have tried so far
1. changed the precision to lowp - no performance boost
2. commented out the v_Coord manipulation as per apple dev doc - no performance boost
3. after commenting distance calculation in shader FPS increased to 30;

still something is eating up 30 fps, dont know where, all helps are highly appreciated.

Thanks

Removing the branches made it finally :slight_smile:

1 Like

Hi ! thanks for helping, I can actually run a shader on COCOS now it’s fine :slight_smile: But i’m not able to update a uniform value yet.

Could someone please show me the C++ / Cocos code to do this plz ? The only turorial I found is this one : http://www.raywenderlich.com/10862/how-to-create-cool-effects-with-custom-shaders-in-opengl-es-2-0-and-cocos2d-2-x but it’s in Objectiv-C and when I try on windows that doesn’t work (I tried many things though)

thanks !

You get the location of the uniform and then set it whenever it changes.

assuming a uniform with name “my_uniform”

uniform float my_uniform;

if uniform doesn’t change set when creating program

/// if at creation use program when created
shaderProgram = GLProgram::createWithFilenames("shaders/vertex.vsh", "shaders/pixel.fsh");

/// if you update uniform, get program from state
auto glProgram = getGLProgramState()->getGLProgram();

/// set uniform (after creating, or during update)
GLint uniformLocation = glGetUniformLocation(prog->getProgram(), "my_uniform");
shaderProgram->setUniformLocationWith1f(uniformLocation, 0.5f);    

Edit: if that doesn’t work, check the cpp-tests for the 3d lighting tests, they set lots of uniforms for lights and matricies

Thanks for the quick answer !

So, I finally managed to use a float uniform which is updated each frame !

Here is the .vhs :

attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord;
uniform float waveData;
varying vec4 vColor;
varying vec2 vTexCoord;
 
void main() 
{
    vColor.rgba = vec4(waveData, waveData, waveData, 1.0);
    vTexCoord = a_texCoord;
    gl_Position = CC_PMatrix * a_position;
}

the .fsh :

varying vec4 vColor;
varying vec2 vTexCoord;

void main()
{
    //to test shader I change every pixel color but you can also use the texture as bellow
    //gl_FragColor = texture2D(CC_Texture0, vTexCoord) * vColor;
    gl_FragColor = vColor;
}

the init func of my sprite :

m_myShader = GLProgram::createWithFilenames("waterMove.vsh", "waterMove.fsh"); 
    m_myShader->retain();

    m_myShader->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION);
    m_myShader->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::VERTEX_ATTRIB_COLOR);
    m_myShader->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORDS);
    m_myShader->link();
    CHECK_GL_ERROR_DEBUG();
    m_myShader->updateUniforms();
    CHECK_GL_ERROR_DEBUG();

    auto glProgramState = GLProgramState::getOrCreateWithGLProgram(m_myShader);
    setGLProgramState(glProgramState);

    getGLProgramState()->setUniformFloat("waveData", 0.5f);

    this->setShaderProgram(m_myShader);

    m_myShader->use();

I set the base uniform value to “0.5” arbitrary.

then in update() I change value to change pixel colors dynamicly :

 m_angleWaveUniform += _dt;   

 while(m_angleWaveUniform > 0.99f)
     m_angleWaveUniform -= 0.98f;

 getGLProgramState()->setUniformFloat("waveData", m_angleWaveUniform);

In fact that’s soooo simple, but as always in Cocos2D there are few good tutorials, some old functions are still here but don’t work anymore, documentation ain’t clear… anyway that’s working, I can now try to make my own shaders :smiley:

I hope that will help someone…

2 Likes