fragment uv flip glsl shader and wondering how i can replace the if statements with working math - glsl

//This has been tested and works in AGK classic
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
#define PROCESSING_TEXTURE_SHADER
varying mediump vec2 uvVarying;
uniform sampler2D texture0;
uniform vec2 rot; //where rot is a vector passed to the shader from my AGK program
void main(void)
{
vec2 p = uvVarying;
if (rot.x ==1.0)
{p.x=rot.x-p.x;}
if (rot.y==1.0)")
{p.y=rot.y-p.y;}
vec3 col = texture2D(texture0, p).rgb;
gl_FragColor = vec4(col, 1.0);
}
without the if statements
i.e and rot.x =0 then "p.x=rot.x-p.x" fails (the same for the second vector rot.y
im looking for a simple math work around that removes the if statement for performance

if you want to remove if statement and your rot.x and rot.y values could be either 0.0 or 1.0, then I would suggest to try with a mix function
vec2 p = mix(uvVarying, rot - uvVarying, rot);

Related

Change texture colors using shaders

I'm trying to change texture colors inside the GLSL context - doing so before the beginning of the OpenGL pipeline is not an option.
I have tried the following approach:
Vertex Shader
attribute highp vec2 a_TexCoord;
uniform highp mat3 u_TextureMatrix;
varying highp vec2 v_TexCoord;
highp vec4 calculatePosition();
void main()
{
gl_Position = calculatePosition();
v_TexCoord = (u_TextureMatrix * vec3(a_TexCoord,1.0)).xy;
}
attribute highp vec2 a_Vertex;
uniform highp mat3 u_TransformMatrix;
uniform highp mat3 u_ProjectionMatrix;
highp vec4 calculatePosition() {
return vec4(u_ProjectionMatrix * u_TransformMatrix * vec3(a_Vertex.xy, 1.0), 1.0);
}
Fragment Shader
uniform lowp float u_Opacity;
lowp vec4 calculatePixel();
void main()
{
gl_FragColor = calculatePixel();
gl_FragColor.a *= u_Opacity;
}
varying mediump vec2 v_TexCoord;
uniform lowp vec4 u_Color;
uniform sampler2D u_Tex0;
lowp vec4 calculatePixel() {
vec4 tex = texture2D(u_Tex0, v_TexCoord);
tex.xyz -= (100.0 / 255.0);
if (tex.x < 0.0) { tex.x += 1.0; }
if (tex.y < 0.0) { tex.y += 1.0; }
if (tex.z < 0.0) { tex.z += 1.0; }
return tex * u_Color;
}
This code works EXCEPT for the cases when Interpolation is applied (GL_LINEAR_MIPMAP_LINEAR), when things start to look really bad because the filtering happens before the Fragment Shader so I don't get to change the colors PRIOR when it's reliable to do so.
I'm developing a game that has as requirement supporting really old hardware (from as early as 2008) and that's why I'm using really obsolete GLSL code (version 120 compatible).
Is there a way to change Texture colors anywhere in the pipeline BEFORE the rasterization kicks in?

How to implement a Color Matrix Filter in a GLSL shader

I would like to implement a Color Matrix Filter in a GLSL shader but couldn't find any documentation regarding this matter. I'm totaly new to the world of shaders (never coded one myself) so please forgive me if my explanation/vocabulary doesn't make mush sense.
Informations I could gather so far:
A color matrix is composed of 5 columns (RGBA + offset) and 4 rows
The values in the first four columns are multiplied with the source red, green, blue, and alpha values respectively. The fifth column value is added (offset)
I believe the largest matrices in GLSL are 4×4 mat4 matrices (excluding the 'offset' column)
The only mat4 I've seen implemented in a shader looks like this:
colorMatrix = (GPUMatrix4x4){{0.3588, 0.7044, 0.1368, 0.0},
{0.2990, 0.5870, 0.1140, 0.0},
{0.2392, 0.4696, 0.0912 ,0.0},
{0,0,0,1.0}
};
Question:
How can implement one ? As stated above I've never coded a GLSL shader before and unfortunately I'm unable to provide an MCVE. I would love to see an example so I can learn from it.
Thank you
EDIT:
I'm working with Processing and this is the only example I've found of vertex and fragment shaders for color rendering:
colorvert.glsl:
uniform mat4 transform;
attribute vec4 position;
attribute vec4 color;
varying vec4 vertColor;
void main() {
gl_Position = transform * position;
vertColor = color;
}
colorfrag.glsl:
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
varying vec4 vertColor;
void main() {
gl_FragColor = vertColor;
}
For starters I would try :
Vertex:
#version 410 core
layout(location = 0) in vec3 in_vertex;
layout(location = 3) in vec4 in_color;
out vec4 color;
void main()
{
const mat4x4 m=mat4x4 // RGBA matrix
(
0.3588, 0.7044, 0.1368, 0.0,
0.2990, 0.5870, 0.1140, 0.0,
0.2392, 0.4696, 0.0912 ,0.0,
0.0 , 0.0 , 0.0 ,1.0
);
const vec4 o=vec4(0.0,0.0,0.0,0.0); // offset
color = (m * in_color) + o; // transformation
gl_Position = vec4(in_vertex,1.0);
}
Fragment:
#version 410 core
in vec4 color;
out vec4 out_color;
void main()
{
out_color=color;
}
Just change the #version, layout and input attributes/uniforms to meet your needs (currently it use default nVidia attribute locations for fixed pipeline)
Now to convert image for example just render textured quad on <-1,+1> vertex coordinate x,y range.
If your matrices or colors change inside fragment (for example as a result of some proceduraly generated stuff) than just move the transformation to fragment shader instead.
You can also change the const to uniform (and move it above main) so you can pass custom parameters on the run ...
In case you need a GLSL start example see:
complete GL+GLSL+VAO/VBO C++ example

Cocos2d-x shader is using invalid offset on texturepacker imported spriteframe

I'm trying to implement a shader for grass in cocos2d-x. The shader works OK on texture loaded with Sprite::create() and it looks like this:
http://i.stack.imgur.com/Rv4rd.png
The problem is that if I'm using Sprite::createWithSpriteFrameName() and applying the same shader it looks like the offsets are wrong when calculating height also because it is moving at a larger degree, like it is using the height of the full texture from plist file:
http://i.stack.imgur.com/of6Ku.png
Here is the shader code:
VSH
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;
#ifdef GL_ES
varying lowp vec4 v_fragmentColor;
varying mediump vec2 v_texCoord;
#else
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
#endif
void main()
{
gl_Position = CC_PMatrix * a_position;
v_fragmentColor = a_color;
v_texCoord = a_texCoord;
}
FSH
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord;
uniform float speed;
uniform float bendFactor;
void main()
{
float height = 1.0 - v_texCoord.y;
float offset = pow(height, 2.5);
offset *= (sin(CC_Time[1] * speed) * bendFactor);
gl_FragColor = texture2D(CC_Texture0, fract(vec2(v_texCoord.x + offset, v_texCoord.y))).rgba;
}
If what is happening is not clear I can provide some videos. Thank you.
EDIT
Here is the code used to generate the grass sprite:
// Smaller grass
auto grass2 = Sprite::createWithSpriteFrameName("grass2.png");
grass2->setAnchorPoint(Vec2(0.5f, 0));
grass2->setPosition(Vec2(230, footer1->getContentSize().height * 0.25f));
// Apply "grass" shader
grass2->setGLProgramState(mat->getTechniqueByName("grass")->getPassByIndex(0)->getGLProgramState()->clone());
grass2->getGLProgramState()->setUniformFloat("speed", RandomHelper::random_real(0.5f, 3.0f));
grass2->getGLProgramState()->setUniformFloat("bendFactor", RandomHelper::random_real(0.1f, 0.2f));
It's hard to tell what's happening without seeing more of your code...
If I should guess I would say that the problem is related to trimming in TexturePacker.
If you set TrimMode=Trim the sprite is stripped from transparency. This makes the sprite smaller. Cocos2d-x also only renders the smaller portion of the sprite, compensating the difference between the original sprite and the trimmed sprite with an offset vector.
I propose that you either try not to trim the sprite or try polygon trimming.
The problem was with TexturePacker trimming but also with offsets in v_texCoord.
The solution was to calculate offsets in cocos2d-x and pass them to shader.
I calculated offsets using following code:
Rect grass2Offset(
grass2->getTextureRect().origin.x / grass2->getTexture()->getContentSize().width,
grass2->getTextureRect().origin.y / grass2->getTexture()->getContentSize().height,
grass2->getTextureRect().size.width / grass2->getTexture()->getContentSize().width,
grass2->getTextureRect().size.height / grass2->getTexture()->getContentSize().height
);
Next I pass the height offset and scale to shader as uniforms using:
grass2->getGLProgramState()->setUniformFloat("heightOffset", grass2Offset.origin.y);
grass2->getGLProgramState()->setUniformFloat("heightScale", 1 / grass2Offset.size.height);
Last, the shader is using the offset like this:
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord;
uniform float speed;
uniform float bendFactor;
uniform float heightOffset;
uniform float heightScale;
void main()
{
float height = 1.0 - (v_texCoord.y - heightOffset) * heightScale;
float offset = pow(height, 2.5);
offset *= (sin(CC_Time[1] * speed) * bendFactor);
gl_FragColor = texture2D(CC_Texture0, fract(vec2(v_texCoord.x + offset, v_texCoord.y))).rgba;
}

Processing multiple light pixel Shader in GLSL

i have written a fragment shader that works just fine with a single light. Now I am trying to adapt it to work with 8 lights, the implement it in Processing. Clearly I am doing something wrong in the math and I cannot see what it is... I have read other posts about this and try to adapt the answer to my problem, no luck though...
////Fragment/////
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
varying vec4 vertColor;
varying vec3 ecNormal;
varying vec3 lightDir;
void main() {
vec3 direction = normalize(lightDir);
vec3 normal = normalize(ecNormal);
float intensity = max(0.0, dot(direction, normal));
gl_FragColor = vec4(intensity, intensity, intensity, 1) * vertColor;
}
////vertex/////
#define PROCESSING_LIGHT_SHADER
uniform mat4 modelview;
uniform mat4 transform;
uniform mat3 normalMatrix;
uniform vec4 lightPosition;
uniform vec3 lightNormal;
attribute vec4 vertex;
attribute vec4 color;
attribute vec3 normal;
varying vec4 vertColor;
varying vec3 ecNormal;
varying vec3 lightDir;
void main() {
gl_Position = transform * vertex;
vec3 ecVertex = vec3(modelview * vertex);
ecNormal = normalize(normalMatrix * normal);
lightDir = normalize(lightPosition.xyz - ecVertex);
vertColor = color;
}
Just making it compile real quick with an online shader tool (http://shdr.bkcore.com/).
You might need to pass the attributes from the veretex shader to varyings for the fragment shader, but I'm not sure, been a while since I wrote shaders.
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
uniform mat4 modelview;
uniform mat4 normalMatrix;
uniform int lightCount;
uniform vec4 lightPosition[8];
varying vec4 vertex; //was attribute, no such thing in frag shaders
varying vec3 normal; //was attribute
varying vec4 vertColor;
void main() {
vec3 vertexCamera = vec3(modelview * vertex);
vec3 transformedNormal = normalize(normalMatrix * vec4(normal,1)).xyz; //was vec3 = normalize(mat4*vec3);
float intensity = 0.0;
for(int i = 0 ; i<8;i++){ //can't loop over a non-constant variable
if(lightCount<i)
{
vec3 direction = normalize(lightPosition[i].xyz - vertexCamera);
intensity += max(0.0, dot(direction, transformedNormal));
}
}
gl_FragColor = vec4(intensity, intensity, intensity, 1) * vertColor;
}

Passing data into different shaders

Lets say my Shaderprogram contains a Vertex- and a Fragmentshader.
How can i pass information straight to the fragmentshader?
When i Use gl_uniform... and specifiy the varaible I want to adress inside the fragmet shader it throws me an error like this:
Using ShaderProgram: The fragment shader uses varying myVarHere, but previous
shader doesnot write to it.
Since I attach the vertexshader first, I found out that I need to "pass the information through" the vertex shader using in and out.
Im not sure if this is the way to go, so my question: Is there a way to tell opengl to adress the variable in a certain shader or am I doing / understanding something horribly wrong?
VertexShader:
#version 130
precision highp float;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
in vec3 vertexData;
in vec3 normalData;
out vec3 normal;
void main(void)
{
normal = (model * view * vec4(normalData, 0)).xyz;
gl_Position = projection * model * view * vec4(vertexData, 1);
}
Fragment:
#version 130
precision highp float;
in vec3 light0; // <- this is what i want to fill with data
const vec3 ambient = vec3(0.0, 0.0, 0.0);
const vec3 lightColor = vec3(0.6, 0.0, 0.0);
in vec3 normal;
out vec4 out_frag_color;
void main(void)
{
float diffuse = clamp(dot(normalize(light0), normalize(normal)), 0.5, 1.0);
out_frag_color = vec4(ambient + diffuse * lightColor, 1.0);
}
It seems like you want light0 to be a uniform.
Just make it a uniform:
#version 130
precision highp float;
uniform vec3 light0;
...