How would you convert this shader to work with version 120? - glsl

Often newer version shaders can be simple to convert but this one uses the function texelFetch which is not available in version 120. Leastways my version is not working:
New version:
in vec4 v_colour;
in vec2 tex_coord;
out vec4 pixel;
uniform sampler2D t0;
uniform float bloom_spread = 1;
uniform float bloom_intensity = 2;
void main() {
ivec2 size = textureSize(t0, 0);
float uv_x = tex_coord.x * size.x;
float uv_y = tex_coord.y * size.y;
vec4 sum = vec4(0.0);
for (int n = 0; n < 9; ++n) {
uv_y = (tex_coord.y * size.y) + (bloom_spread * float(n - 4));
vec4 h_sum = vec4(0.0);
h_sum += texelFetch(t0, ivec2(uv_x - (4.0 * bloom_spread), uv_y), 0);
h_sum += texelFetch(t0, ivec2(uv_x - (3.0 * bloom_spread), uv_y), 0);
h_sum += texelFetch(t0, ivec2(uv_x - (2.0 * bloom_spread), uv_y), 0);
h_sum += texelFetch(t0, ivec2(uv_x - bloom_spread, uv_y), 0);
h_sum += texelFetch(t0, ivec2(uv_x, uv_y), 0);
h_sum += texelFetch(t0, ivec2(uv_x + bloom_spread, uv_y), 0);
h_sum += texelFetch(t0, ivec2(uv_x + (2.0 * bloom_spread), uv_y), 0);
h_sum += texelFetch(t0, ivec2(uv_x + (3.0 * bloom_spread), uv_y), 0);
h_sum += texelFetch(t0, ivec2(uv_x + (4.0 * bloom_spread), uv_y), 0);
sum += h_sum / 9.0;
}
pixel = texture(t0, tex_coord) - ((sum / 9.0) * bloom_intensity);
}
This is my 120 version but it doesn't work, it just makes the texture black:
varying vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;
const float bloom_spread = 1.0;
const float bloom_intensity = 2.0;
uniform vec2 size;
vec4 texelFetch(sampler2D tex, ivec2 size, ivec2 coord) {
return texture2D(tex, vec2(float(coord.x) / float(size.x), float(coord.y) / float(size.y)));
}
void main() {
// ivec2 size = textureSize(u_texture, 0);
float uv_x = v_texCoords.x * size.x;
float uv_y = v_texCoords.y * size.y;
vec4 sum = vec4(0.0);
for (int n = 0; n < 9; ++n) {
uv_y = (v_texCoords.y * size.y) + (bloom_spread * float(n - 4));
vec4 h_sum = vec4(0.0);
h_sum += texelFetch(u_texture, ivec2(size), ivec2(uv_x - (4.0 * bloom_spread), uv_y));
h_sum += texelFetch(u_texture, ivec2(size), ivec2(uv_x - (3.0 * bloom_spread), uv_y));
h_sum += texelFetch(u_texture, ivec2(size), ivec2(uv_x - (2.0 * bloom_spread), uv_y));
h_sum += texelFetch(u_texture, ivec2(size), ivec2(uv_x - bloom_spread, uv_y));
h_sum += texelFetch(u_texture, ivec2(size), ivec2(uv_x, uv_y));
h_sum += texelFetch(u_texture, ivec2(size), ivec2(uv_x + bloom_spread, uv_y));
h_sum += texelFetch(u_texture, ivec2(size), ivec2(uv_x + (2.0 * bloom_spread), uv_y));
h_sum += texelFetch(u_texture, ivec2(size), ivec2(uv_x + (3.0 * bloom_spread), uv_y));
h_sum += texelFetch(u_texture, ivec2(size), ivec2(uv_x + (4.0 * bloom_spread), uv_y));
sum += h_sum / 9.0;
}
gl_FragColor = texture2D(u_texture, v_texCoords) - ((sum / 9.0) * bloom_intensity);
}

Related

OpenGL Triangle pipe around line segment

I would like to ask how can I render in geometry shader a triangle pipe from a line segment?
I first compute perpendicular vector "perp" to the line vector "axis".
Then I rotate the "perp" vector few times by "rotate" function.
Since mesh is composed from 8 vertices I am trying to use "triangle_strip".
My current code :
#version 330 core
layout (lines) in;
layout(triangle_strip, max_vertices = 8) out;//triangle_strip
uniform float u_thickness ;
uniform vec2 u_viewportSize ;
uniform bool u_scale_width_by_zoom ;
in gl_PerVertex
{
vec4 gl_Position;
//float gl_PointSize;
//float gl_ClipDistance[];
} gl_in[];
vec4 rotate(vec4 p, float x, float y, float z,float angle )
{
vec3 q;
q[0] = p[0] * (x*x * (1.0 - cos(angle)) + cos(angle))
+ p[1] * (x*y * (1.0 - cos(angle)) + z * sin(angle))
+ p[2] * (x*z * (1.0 - cos(angle)) - y * sin(angle));
q[1] = p[0] * (y*x * (1.0 - cos(angle)) - z * sin(angle))
+ p[1]* (y*y * (1.0 - cos(angle)) + cos(angle))
+ p[2] * (y*z * (1.0 - cos(angle)) + x * sin(angle));
q[2] = p[0] * (z*x * (1.0 - cos(angle)) + y * sin(angle))
+ p[1] * (z*y * (1.0 - cos(angle)) - x * sin(angle))
+ p[2] * (z*z * (1.0 - cos(angle)) + cos(angle));
return vec4(q, 0.0);
}
void main() {
//https://stackoverflow.com/questions/54686818/glsl-geometry-shader-to-replace-gllinewidth
vec4 p1 = gl_in[0].gl_Position;
vec4 p2 = gl_in[1].gl_Position;
//tube
// Specify the axis to rotate about:
vec4 axis = p2-p1;
float x = axis[0];
float y = axis[1];
float z = axis[2];
axis = normalize(axis);
//float length = hypotf(axis[0], hypotf(axis[1], axis[2]));
float length = sqrt((axis[0]*axis[0]) + sqrt(axis[1]*axis[1]+ axis[2]*axis[2]));
float dir_scalar = (axis[0] > 0.0) ? length : -length;
float xt = axis[0] + dir_scalar;
float dot = -axis[1] / (dir_scalar * xt);
vec3 perp_0 = vec3(dot * xt, 1.0f + dot * axis.y, dot * axis.z);
perp_0 = normalize(perp_0);
vec4 perp = vec4(perp_0,0)*u_thickness*0.001;
//side0
vec4 p1_1 = p1+perp;
vec4 p1_2 = p2+perp;
vec4 perp_rot_2=rotate(perp,x,y,z,60.0 * 3.14 / 180.0);
vec4 p2_1 = p1+perp_rot_2;
vec4 p2_2 = p2+perp_rot_2;
vec4 perp_rot_3=rotate(perp,x,y,z, 120.0 * 3.14 / 180.0);
vec4 p3_1 = p1+perp_rot_3;
vec4 p3_2 = p2+perp_rot_3;
gl_Position = p1_1;
EmitVertex();
gl_Position = p1_2;
EmitVertex();
gl_Position = p2_1;
EmitVertex();
gl_Position = p2_2;
EmitVertex();
gl_Position = p3_1;
EmitVertex();
gl_Position = p3_2;
EmitVertex();
gl_Position = p1_1;
EmitVertex();
gl_Position = p1_2;
EmitVertex();
EndPrimitive();
}
It produces wrong results:

Multiple texture outputs on a different fbo

i'm trying to calculate data using textures, and reading from Ping fbo while writing to Pong fbo.
an explanation picture of what i'm trying to achieve:
here's my call code:
glUseProgram(TexturedShader);
glBindFramebuffer(GL_FRAMEBUFFER, PongFbo);
// glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(n0->PingVao);
Write(ping, n0, TexturedShader);
Write(ping, nN, TexturedShader);
Write(ping, nE, TexturedShader);
Write(ping, nW, TexturedShader);
Write(ping, nS, TexturedShader);
Write(ping, nSE, TexturedShader);
Write(ping, nSW, TexturedShader);
WriteOut();
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
void Write(bool ping, Tabela* N, GLuint Shader)
{
if (ping)
{
glActiveTexture(static_cast<GLenum>(static_cast<int>(GL_TEXTURE0)+N->MyNr()));
glBindTexture(GL_TEXTURE_2D, N->PingTexture);
}
else
{
glActiveTexture(static_cast<GLenum>(static_cast<int>(GL_TEXTURE0)+N->MyNr()));
glBindTexture(GL_TEXTURE_2D, N->PongTexture);
}
glUniform1i(glGetUniformLocation(Shader, N->MyName().c_str()), N->MyNr());
if (glGetUniformLocation(Shader, N->MyName().c_str()) == -1)
{
std::cout << "not bound sucessfully " << Shader << " " << N->MyNr() << " " << N->MyName().c_str() << std::endl;
}
}
void WriteOut()
{
GLenum DrawBuffers[7] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5, GL_COLOR_ATTACHMENT6 };
glDrawBuffers(7, DrawBuffers);
}
For some reason it works without setting layouts on shaders, but only for the first buffer? I also get no errors or missing uniforms.
and my shader:
#version 450 core
in vec2 TexCoords;
layout(location=0) out vec4 n0out;
layout(location=1) out vec4 nNnSnEout;
layout(location=2) out vec4 nWnNEnNWout;
layout(location=3) out vec4 nSEnSWout;
layout(location=4) out vec4 densityout;
layout(location=5) out vec4 velxvelyout;
layout(location=6) out vec4 speed2out;
layout(binding=0) uniform sampler2D n0;
layout(binding=1) uniform sampler2D nNnSnE;
layout(binding=2) uniform sampler2D nWnNEnNW;
layout(binding=3) uniform sampler2D nSEnSW;
layout(binding=4) uniform sampler2D density;
layout(binding=5) uniform sampler2D velxvely;
layout(binding=6) uniform sampler2D speed2;
//uniform vec2 barrier;
float viskoznost = 0.02f;
float omega = 1 / (3 * viskoznost + 0.5); //Relaksacijski cas
float stiri9ne = 4.0 / 9;
float ena9na = 1.0 / 9;
float ena36na = 1.0 / 36;
float nN0 = 0;
float nN = 0;
float nS = 0;
float nE = 0;
float nW = 0;
float nNE = 0;
float nNW = 0;
float nSE = 0;
float nSW = 0;
float ndensity = 0;
float nvelx = 0;
float nvely = 0;
float nspeed2 = 0;
void Trk(){
if (!(gl_FragCoord.x > 300 && gl_FragCoord.x < 301 && gl_FragCoord.y >400 && gl_FragCoord.y < 600))
{
float n = nN0 + nN + nS + nE + nW + nNW + nNE + nSW + nSE;
ndensity = n; // macroscopic density may be needed for plotting
float vx, vy;
float ena9naN = ena9na * n;
float ena36naN = ena36na * n;
if (n > 0)
{
vx = (nE + nNE + nSE - nW - nNW - nSW) / n;
}
else vx = 0;
nvelx = vx; // may be needed for plotting
if (n > 0){
vy = (nN + nNE + nNW - nS - nSE - nSW) / n;
}
else vy = 0;
nvely= vy; //needed for plotting
float vx3 = 3 * vx;
float vy3 = 3 * vy;
float vx2 = vx * vx;
float vy2 = vy * vy;
float vxvy2 = 2 * vx * vy;
float v2 = vx2 + vy2;
nspeed2 = v2; // may be needed for plotting
float v215 = 1.5 * v2;
nN0 += omega * (stiri9ne * n * (1 - v215) - nN0);
nE += omega * (ena9naN * (1 + vx3 + 4.5*vx2 - v215) - nE);
nW += omega * (ena9naN * (1 - vx3 + 4.5*vx2 - v215) - nW);
nN += omega * (ena9naN * (1 + vy3 + 4.5*vy2 - v215) - nN);
nS += omega * (ena9naN * (1 - vy3 + 4.5*vy2 - v215) - nS);
nNE += omega * (ena36naN * (1 + vx3 + vy3 + 4.5*(v2 + vxvy2) - v215) - nNE);
nNW += omega * (ena36naN * (1 - vx3 + vy3 + 4.5*(v2 - vxvy2) - v215) - nNW);
nSE += omega * (ena36naN * (1 + vx3 - vy3 + 4.5*(v2 - vxvy2) - v215) - nSE);
nSW += omega * (ena36naN * (1 - vx3 - vy3 + 4.5*(v2 + vxvy2) - v215) - nSW);
}
}
void main()
{
nN0 = texture(n0, TexCoords).x;
nN = texture(nNnSnE, TexCoords).x;
nS = texture(nNnSnE, TexCoords).y;
nE = texture(nNnSnE, TexCoords).z;
nW = texture(nWnNEnNW, TexCoords).x;
nNE = texture(nWnNEnNW, TexCoords).y;
nNW = texture(nWnNEnNW, TexCoords).z;
nSE = texture(nSEnSW, TexCoords).x;
nSW = texture(nSEnSW, TexCoords).y;
ndensity = texture(density, TexCoords).x;
nvelx = texture(velxvely, TexCoords).x;
nvely = texture(velxvely, TexCoords).y;
nspeed2 = texture(speed2, TexCoords).x;
Trk();
n0out.x = nN0;
nNnSnEout.xyz = vec3(nN,nS,nE);
nWnNEnNWout.xyz = vec3(nW,nNE,nNW);
nSEnSWout.xy = vec2(nSE,nSW);
densityout.x = ndensity;
velxvelyout.xy = vec2(nvelx, nvely);
speed2out.x = nspeed2;
}
edit: fixed the code
After days, I have finally fixed the problem, it appeared that i had to use layouts(bindings) to bind the input textures, and then use glDrawBuffers to tell it which texture should be written on to the current FBO.
The read FBO didn't matter, i only had to call texture names (those called with glGenTextures), and didn't have to specify the fbo at all.
I've updated the code in the question.

OpenGL Matrix Multiplication C++

So I am trying to multiply rotation and translation matrices together and I can't quite figure out what is going wrong.
If, in the program I multiply a translation matrix by a rotation matrix then send that matrix as a uniform to my shader program I end up with the object becoming 2D then 3D again as it spins [ https://a.pomf.se/xvvrsg.mp4 ] (object on the right).
shader.setUniformMat4("model_matrix", Matrix4::translation(Vector3(10.0f, 0.0f, 0.0f)) * Matrix4::rotation(rotation, Vector3(0.0f, 1.0f, 0.0f)));
(vertex shader)
#version 330 core
layout (location = 0) in vec4 in_position;
layout (location = 1) in vec4 in_normal;
uniform mat4 pr_matrix;
uniform mat4 vw_matrix = mat4(1.0);
uniform mat4 model_matrix = mat4(1.0);
out vec4 pos;
out vec4 normal;
void main()
{
pos = pr_matrix * vw_matrix * model_matrix * in_position;
normal = in_normal;
gl_Position = pos;
}
However if I send my individual translation and rotation matrices as separate uniforms and then multiply them in the shader to create my model matrix it works as intended [ https://a.pomf.se/jyxpnb.mp4 ] (object on the right).
shader.setUniformMat4("translation_matrix", Matrix4::translation(Vector3(10.0f, 0.0f, 0.0f)));
shader.setUniformMat4("rotation_matrix", Matrix4::rotation(rotation, Vector3(0.0f, 1.0f, 0.0f)));
shader.setUniformMat4("scale_matrix", Matrix4::identity());
(vertex shader)
#version 330 core
layout (location = 0) in vec4 in_position;
layout (location = 1) in vec4 in_normal;
uniform mat4 pr_matrix;
uniform mat4 vw_matrix = mat4(1.0);
uniform mat4 translation_matrix = mat4(1.0);
uniform mat4 rotation_matrix = mat4(1.0);
uniform mat4 scale_matrix = mat4(1.0);
out vec4 pos;
out vec4 normal;
void main()
{
mat4 model_matrix = translation_matrix * rotation_matrix * scale_matrix;
pos = pr_matrix * vw_matrix * model_matrix * in_position;
normal = in_normal;
gl_Position = pos;
}
This leads me to believe that there must be an error in my multiplication of matrices, this is how I am currently doing it:
Matrix4 &Matrix4::multiply(const Matrix4 &other)
{
elements[0] = elements[0] * other.elements[0] + elements[4] * other.elements[1] + elements[8] * other.elements[2] + elements[12] * other.elements[3];
elements[1] = elements[1] * other.elements[0] + elements[5] * other.elements[1] + elements[9] * other.elements[2] + elements[13] * other.elements[3];
elements[2] = elements[2] * other.elements[0] + elements[6] * other.elements[1] + elements[10] * other.elements[2] + elements[14] * other.elements[3];
elements[3] = elements[3] * other.elements[0] + elements[7] * other.elements[1] + elements[11] * other.elements[2] + elements[15] * other.elements[3];
elements[4] = elements[0] * other.elements[4] + elements[4] * other.elements[5] + elements[8] * other.elements[6] + elements[12] * other.elements[7];
elements[5] = elements[1] * other.elements[4] + elements[5] * other.elements[5] + elements[9] * other.elements[6] + elements[13] * other.elements[7];
elements[6] = elements[2] * other.elements[4] + elements[6] * other.elements[5] + elements[10] * other.elements[6] + elements[14] * other.elements[7];
elements[7] = elements[3] * other.elements[4] + elements[7] * other.elements[5] + elements[11] * other.elements[6] + elements[15] * other.elements[7];
elements[8] = elements[0] * other.elements[8] + elements[4] * other.elements[9] + elements[8] * other.elements[10] + elements[12] * other.elements[11];
elements[9] = elements[1] * other.elements[8] + elements[5] * other.elements[9] + elements[9] * other.elements[10] + elements[13] * other.elements[11];
elements[10] = elements[2] * other.elements[8] + elements[6] * other.elements[9] + elements[10] * other.elements[10] + elements[14] * other.elements[11];
elements[11] = elements[3] * other.elements[8] + elements[7] * other.elements[9] + elements[11] * other.elements[10] + elements[15] * other.elements[11];
elements[12] = elements[0] * other.elements[12] + elements[4] * other.elements[13] + elements[8] * other.elements[14] + elements[12] * other.elements[15];
elements[13] = elements[1] * other.elements[12] + elements[5] * other.elements[13] + elements[9] * other.elements[14] + elements[13] * other.elements[15];
elements[14] = elements[2] * other.elements[12] + elements[6] * other.elements[13] + elements[10] * other.elements[14] + elements[14] * other.elements[15];
elements[15] = elements[3] * other.elements[12] + elements[7] * other.elements[13] + elements[11] * other.elements[14] + elements[15] * other.elements[15];
return *this;
}
I did have a nested loop to do this but I ended up writing it all out while trying to find out an answer to this problem. Bear in mind the matrices are in column major and do not get transposed by OpenGL
The rotation and translation matrices are as follows but I don't believe there is any problem with them:
Matrix4 Matrix4::translation(const Vector3 &translation)
{
Matrix4 result(1.0f);
result.elements[0 + 3 * 4] = translation.x;
result.elements[1 + 3 * 4] = translation.y;
result.elements[2 + 3 * 4] = translation.z;
return result;
}
Matrix4 Matrix4::rotation(float angle, const Vector3 &axis)
{
Matrix4 result(1.0f);
float r = toRadians(angle);
float c = (float)cos(r);
float s = (float)sin(r);
float cFlip = 1.0f - c;
result.elements[0 + 0 * 4] = axis.x * cFlip + c;
result.elements[1 + 0 * 4] = axis.y * axis.x * cFlip + axis.z * s;
result.elements[2 + 0 * 4] = axis.x * axis.z * cFlip - axis.y * s;
result.elements[0 + 1 * 4] = axis.x * axis.y * cFlip - axis.z * s;
result.elements[1 + 1 * 4] = axis.y * cFlip + c;
result.elements[2 + 1 * 4] = axis.y * axis.z * cFlip + axis.x * s;
result.elements[0 + 2 * 4] = axis.x * axis.y * cFlip + axis.y * s;
result.elements[1 + 2 * 4] = axis.y * axis.z * cFlip - axis.x * s;
result.elements[2 + 2 * 4] = axis.z * cFlip + c;
return result;
}
Any ideas on what the problem here could be or how to fix it would be greatly appreciated :^)
At your multiply function, you wrote:
elements[0] = elements[0] * other.elements[0] ...
...
Notice that element[0] got its contents actualized now and then you do:
elements[8] = elements[0] * other.elements[8] ...
which use the new value and not the original one. I guess, you want to make a copy of your original matrix before doing this multiplication
opssss !! i just saw !!!
in your multiply, your output matrice is the first input matrix, so the latest operations are calculated with coefficient of the multiplied matrix !! :
elements[0] = elements[0] * .....
....
elements[4] = elements[0] * ..... /* here element[ 0 ] is the top left
element of the multiplied matix */
moreover, operator* shouldn't modfify (nor return) one of his operand, operator*= is here for that

GLSL Fragment shader slowdown

I have been spending the last few days writing a fragment shader that will handle the background for a 2d game im making. However, today I noticed that my cloud rendering is extremley slow (drop from 3000 to 300 fps) when rendering.
At first I thought that it was because I had done something stupid when generating the clouds, but after some experiments I noticed that the slowdown only happned when I added the clouds t the gl_FragColor. Calculating them seemed to not have any impact on performance.
I generate the clouds like this:
float rand(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
float hash( float n ) //Borrowed from voltage
{
return fract(sin(n)*43758.5453);
}
float fBmWRand( vec2 p )//Borroowed from Mark Sleith
{
float f = 0.0;
f += 0.50000*rand( p ); p = p*2.02;
f += 0.25000*rand( p ); p = p*2.03;
f += 0.12500*rand( p ); p = p*2.01;
f += 0.06250*rand( p ); p = p*2.04;
f += 0.03125*rand( p );
return f/0.984375;
}
float noise( in vec2 x )//Borroowed from Mark Sleith
{
vec2 p = floor(x);
vec2 f = fract(x);
f = f*f*(3.0-2.0*f);
float n = p.x + p.y*57.0;
float res = mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x), mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y);
return res;
}
float fbm( vec2 p ) //Borroowed from Mark Sleith
{
float f = 0.0;
f += 0.50000*noise( p ); p = p*2.02;
f += 0.25000*noise( p ); p = p*2.03;
f += 0.12500*noise( p ); p = p*2.01;
f += 0.06250*noise( p ); p = p*2.04;
f += 0.03125*noise( p );
return f/0.984375;
}
vec3 bgGradient()
{
//Getting the height of the current pixel
float height = gl_FragCoord.y / iResolution.y;
//Calculating the brightness of the pixel
float brightness = 1.0 - 0.4 * height;
//Combining everything into a background
vec3 grad = vec3(1., 1., 1.);// * brightness;
return grad;
}
bool star()
{
/*//Getting a position to run random calculations with
float pos = (gl_FragCoord.x / iResolution.x) * (gl_FragCoord.y / iResolution.y) + 0.5;
if(hash(pos) < 0.001)
{
return true;
}
return false*/;
if(fBmWRand(gl_FragCoord.xy / iResolution.xy) < 0.08)
{
return true;
}
return false;
}
float cloudFadeDist = 0.1; //The distance at which the clouds will start fading away
vec4 clouds( vec2 point )
{
vec4 result = vec4(0., 0., 0., 0.);
//Checking if the cloud is above
float fbmResult = fbm(point * 5.);
if(fbmResult > overcast)
{
result = vec4(fbmResult, fbmResult, fbmResult, 1.0);
//result = vec4(1., 1., 1., 1.);
}
else if(fbmResult > overcast - (cloudFadeDist / resFact)) //Outlining the clouds
{
float dist = overcast - fbmResult;
float colorFac = 1.0 - dist / (cloudFadeDist / resFact);
if(colorFac > 0.0001)
{
result = vec4(fbmResult, fbmResult, fbmResult, colorFac);
}
}
//Finer details
float fbmDetail = fbm(point * 20.);
vec4 details = vec4( 0.7 + fbmDetail, 0.7 + fbmDetail, 0.7 + fbmDetail, 1.0);
//result = mix(result, details, result.a);
result = result * details;
result = result * details;
return result;
}
And I add the clouds to the rest of the "image" with this
//Generating the clouds
vec4 cloudLayer = vec4(0., 0., 0., 0.);
for(int i = 0; i < 4; i++)
{
//clouds( (15.0 * float(i)) + gl_FragCoord.xy / iResolution.xy + posX * float(i + 1));
/*vec4 cloud = clouds( vec2((15. * float(i)) + gl_FragCoord.x / iResolution.x + posX * float(i + 1)),
(15. * float(i)) + gl_FragCoord.y / iResoulution.y);*/
vec4 cloud = clouds( vec2( (15. * float(i)) + gl_FragCoord.x / iResolution.x + posX * float(i + 1),
(15. * float(i)) + gl_FragCoord.y / iResolution.y + posY * float(i + 1)));
//finalColor = finalColor + vec4(cloud, 1.);
cloudLayer = mix(cloudLayer, cloud, cloud.a);
}
if(time > nStart || time < nEnd) //Nighttime
{
finalColor = finalColor * nSky;
finalColor = mix(finalColor, starLayer, starLayer.a);
cloudLayer = cloudLayer * nCloud;
//finalColor = mix(finalColor, cloudLayer, cloudLayer.a);
vec4 genericColor = cloudLayer;
finalColor = mix(finalColor, cloudLayer, cloudLayer.a);
//finalColor = vec4(nSky.r, nSky.g, nSky.b, 1.0);
}
else if(time > dStart && time < dEnd)
{
finalColor = finalColor * dSky;
//cloudLayer = cloudLayer * dCloud;
finalColor = mix(finalColor, cloudLayer, cloudLayer.a);
}
else if(time > dEnd && time < nStart) //Evening
{
float timeFact = (time - dEnd) / (nStart - dEnd);
//Calculating the diffirence between night and day
vec4 skyDiff = vec4(nSky.r - dSky.r, nSky.g - dSky.g, nSky.b - dSky.b, 1.);
vec4 skyColor = vec4(dSky.r + (skyDiff.r * timeFact), dSky.g + (skyDiff.g * timeFact), dSky.b + (skyDiff.b * timeFact), 1.);
finalColor = skyColor;
//Stars
finalColor = mix(finalColor, starLayer, starLayer * timeFact);
//Clouds
vec4 cloudDiff = vec4(nCloud.r - dCloud.r, nCloud.g - dCloud.g, nCloud.b - dCloud.b, 1.);
vec4 cloudColor = vec4(dCloud.r + (cloudDiff.r * timeFact), dCloud.g + (cloudDiff.g * timeFact), dCloud.b + (cloudDiff.b * timeFact), 1.);
vec4 cloudLayer = cloudLayer * cloudColor;
finalColor = mix(finalColor, cloudLayer, cloudLayer.a);
}
else if(time > nEnd && time < dStart) //Evening
{
float timeFact = (time - nEnd) / (dStart - nEnd);
//Calculating the diffirence between night and day
vec4 skyDiff = vec4(dSky.r - nSky.r, dSky.g - nSky.g, dSky.b - nSky.b, 1.);
vec4 skyColor = vec4(nSky.r + (skyDiff.r * timeFact), nSky.g + (skyDiff.g * timeFact), nSky.b + (skyDiff.b * timeFact), 1.);
finalColor = skyColor;
//Stars
finalColor = mix(finalColor, starLayer, starLayer * 1. - timeFact);
//Clouds
vec4 cloudDiff = vec4(dCloud.r - nCloud.r, dCloud.g - nCloud.g, dCloud.b - nCloud.b, 1.);
vec4 cloudColor = vec4(nCloud.r + (cloudDiff.r * timeFact), nCloud.g + (cloudDiff.g * timeFact), nCloud.b + (cloudDiff.b * timeFact), 1.);
vec4 cloudLayer = cloudLayer * cloudColor;
finalColor = mix(finalColor, cloudLayer, cloudLayer.a);
}
gl_FragColor = finalColor;
The slowdown only happens when I do:
gl_FragColor = finalColor;
I also double the FPS from 300 to 600 if I remove the details part of the cloud generation
Is there something I have done wrong or is it just natural for the shader to be this performance intensive when I do something like this.
For reference, this is the whole shader
uniform vec2 iResolution;
uniform vec2 iMouse;
uniform float time;
uniform float overcast;
uniform float posX;
uniform float posY;
uniform vec4 dSky; //The color of the sky during the day
uniform vec4 nSky; //The color of the sky during the night
uniform vec4 dCloud; //The color of the clouds at day
uniform vec4 nCloud; //The color of the clouds at night
float resFact = iResolution.x / 500;
//float overcast = iMouse.y / iResolution.y;
//float posX = iMouse.x / iResolution.x;
/*float nSkyR = 0.05;
float nSkyG = 0.05;
float nSkyB = 0.39;*/
float rand(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
float hash( float n ) //Borrowed from voltage
{
return fract(sin(n)*43758.5453);
}
float fBmWRand( vec2 p )//Borroowed from Mark Sleith
{
float f = 0.0;
f += 0.50000*rand( p ); p = p*2.02;
f += 0.25000*rand( p ); p = p*2.03;
f += 0.12500*rand( p ); p = p*2.01;
f += 0.06250*rand( p ); p = p*2.04;
f += 0.03125*rand( p );
return f/0.984375;
}
float noise( in vec2 x )//Borroowed from Mark Sleith
{
vec2 p = floor(x);
vec2 f = fract(x);
f = f*f*(3.0-2.0*f);
float n = p.x + p.y*57.0;
float res = mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x), mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y);
return res;
}
float fbm( vec2 p ) //Borroowed from Mark Sleith
{
float f = 0.0;
f += 0.50000*noise( p ); p = p*2.02;
f += 0.25000*noise( p ); p = p*2.03;
f += 0.12500*noise( p ); p = p*2.01;
f += 0.06250*noise( p ); p = p*2.04;
f += 0.03125*noise( p );
return f/0.984375;
}
vec3 bgGradient()
{
//Getting the height of the current pixel
float height = gl_FragCoord.y / iResolution.y;
//Calculating the brightness of the pixel
float brightness = 1.0 - 0.4 * height;
//Combining everything into a background
vec3 grad = vec3(1., 1., 1.);// * brightness;
return grad;
}
bool star()
{
/*//Getting a position to run random calculations with
float pos = (gl_FragCoord.x / iResolution.x) * (gl_FragCoord.y / iResolution.y) + 0.5;
if(hash(pos) < 0.001)
{
return true;
}
return false*/;
if(fBmWRand(gl_FragCoord.xy / iResolution.xy) < 0.08)
{
return true;
}
return false;
}
float cloudFadeDist = 0.1; //The distance at which the clouds will start fading away
vec4 clouds( vec2 point )
{
vec4 result = vec4(0., 0., 0., 0.);
//Checking if the cloud is above
float fbmResult = fbm(point * 5.);
if(fbmResult > overcast)
{
result = vec4(fbmResult, fbmResult, fbmResult, 1.0);
//result = vec4(1., 1., 1., 1.);
}
else if(fbmResult > overcast - (cloudFadeDist / resFact)) //Outlining the clouds
{
float dist = overcast - fbmResult;
float colorFac = 1.0 - dist / (cloudFadeDist / resFact);
if(colorFac > 0.0001)
{
result = vec4(fbmResult, fbmResult, fbmResult, colorFac);
}
}
//Finer details
float fbmDetail = fbm(point * 20.);
vec4 details = vec4( 0.7 + fbmDetail, 0.7 + fbmDetail, 0.7 + fbmDetail, 1.0);
//result = mix(result, details, result.a);
result = result * details;
result = result * details;
return result;
}
vec2 sunPos = vec2(0.15, 0.1);
float sunWidth = 0.03;
float sunGlow = 0.015;
float sunR = 1.;
float sunG = 1.;
float sunB = 0.8;
vec4 sun()
{
vec4 result = vec4(0., 0., 0., 0.);
float xPos = gl_FragCoord.x / iResolution.x;
float yPos = gl_FragCoord.y / iResolution.x;
float xDist = xPos - sunPos.x;
float yDist = yPos - sunPos.y;
float dist = sqrt(pow(xDist, 2.) + pow(yDist, 2.));
if(dist < sunWidth)
{
result = vec4(sunR, sunG, sunB, 1.);
}
else if(dist < sunWidth + sunGlow)
{
float distFact = (dist - sunWidth) / sunGlow;
result = vec4(sunR, sunG, sunB , 1. - distFact);
}
return result;
}
float nStart = 2200;
float nEnd = 600;
float dStart = 800;
float dEnd = 2000;
void main(void)
{
//Cretaing the final color variable and adding the gradient
vec4 finalColor = vec4(bgGradient(), 1.0);
//Creating stars
vec4 starLayer = vec4(0., 0., 0., 0.);
if(star() == true)
{
starLayer = vec4(1., 1., 1., 1.); //Make the pixel very bright
}
//Generating the clouds
vec4 cloudLayer = vec4(0., 0., 0., 0.);
for(int i = 0; i < 4; i++)
{
//clouds( (15.0 * float(i)) + gl_FragCoord.xy / iResolution.xy + posX * float(i + 1));
/*vec4 cloud = clouds( vec2((15. * float(i)) + gl_FragCoord.x / iResolution.x + posX * float(i + 1)),
(15. * float(i)) + gl_FragCoord.y / iResoulution.y);*/
vec4 cloud = clouds( vec2( (15. * float(i)) + gl_FragCoord.x / iResolution.x + posX * float(i + 1),
(15. * float(i)) + gl_FragCoord.y / iResolution.y + posY * float(i + 1)));
//finalColor = finalColor + vec4(cloud, 1.);
cloudLayer = mix(cloudLayer, cloud, cloud.a);
}
if(time > nStart || time < nEnd) //Nighttime
{
finalColor = finalColor * nSky;
finalColor = mix(finalColor, starLayer, starLayer.a);
cloudLayer = cloudLayer * nCloud;
//finalColor = mix(finalColor, cloudLayer, cloudLayer.a);
vec4 genericColor = cloudLayer;
finalColor = mix(finalColor, cloudLayer, cloudLayer.a);
//finalColor = vec4(nSky.r, nSky.g, nSky.b, 1.0);
}
else if(time > dStart && time < dEnd)
{
finalColor = finalColor * dSky;
//cloudLayer = cloudLayer * dCloud;
finalColor = mix(finalColor, cloudLayer, cloudLayer.a);
}
else if(time > dEnd && time < nStart) //Evening
{
float timeFact = (time - dEnd) / (nStart - dEnd);
//Calculating the diffirence between night and day
vec4 skyDiff = vec4(nSky.r - dSky.r, nSky.g - dSky.g, nSky.b - dSky.b, 1.);
vec4 skyColor = vec4(dSky.r + (skyDiff.r * timeFact), dSky.g + (skyDiff.g * timeFact), dSky.b + (skyDiff.b * timeFact), 1.);
finalColor = skyColor;
//Stars
finalColor = mix(finalColor, starLayer, starLayer * timeFact);
//Clouds
vec4 cloudDiff = vec4(nCloud.r - dCloud.r, nCloud.g - dCloud.g, nCloud.b - dCloud.b, 1.);
vec4 cloudColor = vec4(dCloud.r + (cloudDiff.r * timeFact), dCloud.g + (cloudDiff.g * timeFact), dCloud.b + (cloudDiff.b * timeFact), 1.);
vec4 cloudLayer = cloudLayer * cloudColor;
finalColor = mix(finalColor, cloudLayer, cloudLayer.a);
}
else if(time > nEnd && time < dStart) //Evening
{
float timeFact = (time - nEnd) / (dStart - nEnd);
//Calculating the diffirence between night and day
vec4 skyDiff = vec4(dSky.r - nSky.r, dSky.g - nSky.g, dSky.b - nSky.b, 1.);
vec4 skyColor = vec4(nSky.r + (skyDiff.r * timeFact), nSky.g + (skyDiff.g * timeFact), nSky.b + (skyDiff.b * timeFact), 1.);
finalColor = skyColor;
//Stars
finalColor = mix(finalColor, starLayer, starLayer * 1. - timeFact);
//Clouds
vec4 cloudDiff = vec4(dCloud.r - nCloud.r, dCloud.g - nCloud.g, dCloud.b - nCloud.b, 1.);
vec4 cloudColor = vec4(nCloud.r + (cloudDiff.r * timeFact), nCloud.g + (cloudDiff.g * timeFact), nCloud.b + (cloudDiff.b * timeFact), 1.);
vec4 cloudLayer = cloudLayer * cloudColor;
finalColor = mix(finalColor, cloudLayer, cloudLayer.a);
}
//finalColor = vec4(1., 0., 0., 1.);
//vec4 sunColor = sun();
//finalColor = mix(finalColor, sunColor, sunColor.a);
//If there is a star
/*if(star() == true)
{
finalColor = vec4(1., 1., 1., 1.); //Make the pixel very bright
}*/
/*for(int i = 0; i < 4; i++)
{
//clouds( (15.0 * float(i)) + gl_FragCoord.xy / iResolution.xy + posX * float(i + 1));
//vec4 cloud = clouds( vec2((15. * float(i)) + gl_FragCoord.x / iResolution.x + posX * float(i + 1)),
(15. * float(i)) + gl_FragCoord.y / iResoulution.y);
vec4 cloud = clouds( vec2( (15. * float(i)) + gl_FragCoord.x / iResolution.x + posX * float(i + 1),
(15. * float(i)) + gl_FragCoord.y / iResolution.y + posY * float(i + 1)));
//finalColor = finalColor + vec4(cloud, 1.);
finalColor = mix(finalColor, cloud, cloud.a);
}*/
gl_FragColor = finalColor;
}
And a working version without the time stuff can be found here to get an idea of what the shader actually does
Generally shader compilers (being either glsl/hlsl) are pretty good at removing dead code.
So if you calculate some value but don't use it, the compiler will just strip it off before to send the shader bytecode to the graphics card. So in the final compiled version the calculation will actually just not happen.
As soon as you start using this value (which you do as soon as soon you assign it to gl_FragColor) then it's actually "really" integrated in your final shader.
And noise calculations are generally quite ALU intensive, so a slowdown to 300 is not unusual (and actually not even too bad, depending on which card you use).

GLSL Shader Ported From HLSL Is Not Working

I have this HLSL Shader for blur:
struct VS_INPUT
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
float4 Color : TEXCOORD1;
};
struct VS_OUTPUT
{
float4 Position : POSITION0;
float4 Color : COLOR0;
float2 TexCoord : TEXCOORD0;
};
float4x4 al_projview_matrix;
VS_OUTPUT vs_main(VS_INPUT Input)
{
VS_OUTPUT Output;
Output.Position = mul(Input.Position, al_projview_matrix);
Output.Color = Input.Color;
Output.TexCoord = Input.TexCoord;
return Output;
}
Frag
texture al_tex;
sampler2D s = sampler_state {
texture = <al_tex>;
};
int tWidth;
int tHeight;
float blurSize = 5.0;
float4 ps_main(VS_OUTPUT Input) : COLOR0
{
float2 pxSz = float2(1.0 / tWidth,1.0 / tHeight);
float4 outC = 0;
float outA = 0;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,-4.0 * pxSz.y * blurSize)).a * 0.05;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,-3.0 * pxSz.y * blurSize)).a * 0.09;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,-2.0 * pxSz.y * blurSize)).a * 0.12;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,-pxSz.y * blurSize)).a * 0.15;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,0)).a * 0.16;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,pxSz.y * blurSize)).a * 0.15;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,2.0 * pxSz.y * blurSize)).a * 0.12;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,3.0 * pxSz.y * blurSize)).a * 0.09;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,4.0 * pxSz.y * blurSize)).a * 0.05;
outC.a = outA;
return outC;
}
There is a similar one for horizontal...
The idea is, I provide tWidth, tHeight for the texture with and height, and use that to get the 'size' of a pixel relative to UV coords.
I then use this to do normal blur by taking a weighted average of neighbors.
I ported this to GLSL:
attribute vec4 al_pos;
attribute vec4 al_color;
attribute vec2 al_texcoord;
uniform mat4 al_projview_matrix;
varying vec4 varying_color;
varying vec2 varying_texcoord;
void main()
{
varying_color = al_color;
varying_texcoord = al_texcoord;
gl_Position = al_projview_matrix * al_pos;
}
Frag
uniform sampler2D al_tex;
varying float blurSize;
varying float tWidth;
varying float tHeight;
varying vec2 varying_texcoord;
varying vec4 varying_color;
void main()
{
vec4 sum = vec4(0.0);
vec2 pxSz = vec2(1.0 / tWidth,1.0 / tHeight);
// blur in x
// take nine samples, with the distance blurSize between them
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,-4.0 * pxSz.y * blurSize))* 0.05;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,-3.0 * pxSz.y * blurSize))* 0.09;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,-2.0 * pxSz.y * blurSize))* 0.12;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,-pxSz.y * blurSize))* 0.15;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,0))* 0.16;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,pxSz.y * blurSize))* 0.15;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,2.0 * pxSz.y * blurSize))* 0.12;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,3.0 * pxSz.y * blurSize))* 0.09;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,4.0 * pxSz.y * blurSize))* 0.05;
gl_FragColor = varying_color * sum;
}
This is a little different, but it's the same logic. I convert pixel coords to UV coords, and multiply by the blur factor, same as the hlsl factor. Yet, the glsl one gives me an unblurred, slightly more transparent version of the original.
What could cause this?
In your fragment shader, you have:
varying vec4 varying_color;
[...]
gl_FragColor = varying_color;
so all the texture fetches and calculations you do don't have any effect on the final shader output (and are likely to be completely removed by the compiler). You probably want to output sum or to modify it, e.g. with gl_FragColor = varying_color * sum; or whatever effect you want to achieve.
Another thing: in the frag shader, you define varyings for the texture size, but you don't pass them from the vertex shader. Those should be uniforms (or, in modern GLSL, there is also the textureSize() GLSL function which allows you to directly sccess that values without explicitely passing them).