Multiple texture outputs on a different fbo - opengl

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.

Related

Compute Normals After Vertex Deformation?

I am coding a vertex and a fragment shader trying to distort the surface of some water and then computing blinn-phong lighting on the surface. I am able to successfully compute the deformed matrices with a simple noise function, but how can I find the distorted normals? Since it isn't a linear transformation I am stuck, could anyone help?
Here are the relevant files:
vertex shader:
#version 150
uniform mat4 u_Model;
uniform mat4 u_ModelInvTr;
uniform mat4 u_ViewProj;
uniform vec4 u_Color;
uniform int u_Time;
in vec4 vs_Pos; // The array of vertex positions passed to the shader
in vec4 vs_Nor; // The array of vertex normals passed to the shader
in vec4 vs_Col; // The array of vertex colors passed to the shader.
in vec2 vs_UV; // UV coords for texture to pass thru to fragment shader
in float vs_Anim; // 0.f or 1.f To pass thru to fragment shader
in float vs_T2O;
out vec4 fs_Pos;
out vec4 fs_Nor;
out vec4 fs_LightVec;
out vec4 fs_Col;
out vec2 fs_UVs;
out float fs_Anim;
out float fs_dimVal;
out float fs_T2O;
uniform vec4 u_CamPos;
out vec4 fs_CamPos;
const vec4 lightDir = normalize(vec4(0.0, 1.f, 0.0, 0));
mat4 rotationMatrix(vec3 axis, float angle) {
axis = normalize(axis);
float s = sin(angle);
float c = cos(angle);
float oc = 1.0 - c;
return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0,oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);
}
vec4 rotateLightVec(float deg, vec4 LV) {
mat4 R = rotationMatrix(vec3(0,0,1), deg);
return R * LV;
}
float random1(vec3 p) {
return fract(sin(dot(p, vec3(127.1, 311.7, 191.999)))*43758.5453);
}
vec3 random2( vec3 p ) {
return fract( sin( vec3(dot(p, vec3(127.1, 311.7, 58.24)), dot(p, vec3(269.5, 183.3, 657.3)), dot(p, vec3(420.69, 69.420, 469.20))) ) * 43758.5453);
}
void main()
{
fs_Col = vs_Col;
fs_UVs = vs_UV;
fs_Anim = vs_Anim;
fs_T2O = vs_T2O;
mat3 invTranspose = mat3(u_ModelInvTr);
fs_Nor = vec4(invTranspose * vec3(vs_Nor), 0);
vec4 modelposition = u_Model * vs_Pos;
if (vs_Anim != 0) { // if we want to animate this surface
// check region in texture to decide which animatable type is drawn
bool lava = fs_UVs.x >= 13.f/16.f && fs_UVs.y < 2.f/16.f;
bool water = !lava && fs_UVs.x >= 13.f/16.f && fs_UVs.y <= 4.f/16.f;
if (water) {
// define an oscillating time so that model can transition back and forth
float t = (cos(u_Time * 0.05) + 1)/2; // u_Time increments by 1 every frame. Domain [0,1]
vec3 temp = random2(vec3(modelposition.x, modelposition.y, modelposition.z)); // range [0, 1]
temp = (temp - 0.5)/25; // [0, 1/scalar]
modelposition.x = mix(modelposition.x - temp.x, modelposition.x + temp.x, t);
modelposition.y = mix(modelposition.y - temp.y, modelposition.y + 3*temp.y, t);
modelposition.z = mix(modelposition.z - temp.z, modelposition.z + temp.z, t);
} else if (lava) {
// define an oscillating time so that model can transition back and forth
float t = (cos(u_Time * 0.01) + 1)/2; // u_Time increments by 1 every frame. Domain [0,1]
vec3 temp = random2(vec3(modelposition.x, modelposition.y, modelposition.z)); // range [0, 1]
temp = (temp - 0.5)/25; // [0, 1/scalar]
modelposition.x = mix(modelposition.x - temp.x, modelposition.x + temp.x, t);
modelposition.y = mix(modelposition.y - temp.y, modelposition.y + 3*temp.y, t);
modelposition.z = mix(modelposition.z - temp.z, modelposition.z + temp.z, t);
}
}
fs_dimVal = random1(modelposition.xyz/100.f);
fs_LightVec = rotateLightVec(0.001 * u_Time, lightDir); // Compute the direction in which the light source lies
fs_CamPos = u_CamPos; // uniform handle for the camera position instead of the inverse
fs_Pos = modelposition;
gl_Position = u_ViewProj * modelposition;// gl_Position is a built-in variable of OpenGL which is
// used to render the final positions of the geometry's vertices
}
fragment shader:
#version 330
uniform vec4 u_Color; // The color with which to render this instance of geometry.
uniform sampler2D textureSampler;
uniform int u_Time;
uniform mat4 u_ViewProj;
uniform mat4 u_Model;
in vec4 fs_Pos;
in vec4 fs_Nor;
in vec4 fs_LightVec;
in vec4 fs_Col;
in vec2 fs_UVs;
in float fs_Anim;
in float fs_T2O;
in float fs_dimVal;
out vec4 out_Col;
in vec4 fs_CamPos;
float random1(vec3 p) {
return fract(sin(dot(p,vec3(127.1, 311.7, 191.999)))
*43758.5453);
}
float random1b(vec3 p) {
return fract(sin(dot(p,vec3(169.1, 355.7, 195.999)))
*95751.5453);
}
float mySmoothStep(float a, float b, float t) {
t = smoothstep(0, 1, t);
return mix(a, b, t);
}
float cubicTriMix(vec3 p) {
vec3 pFract = fract(p);
float llb = random1(floor(p) + vec3(0,0,0));
float lrb = random1(floor(p) + vec3(1,0,0));
float ulb = random1(floor(p) + vec3(0,1,0));
float urb = random1(floor(p) + vec3(1,1,0));
float llf = random1(floor(p) + vec3(0,0,1));
float lrf = random1(floor(p) + vec3(1,0,1));
float ulf = random1(floor(p) + vec3(0,1,1));
float urf = random1(floor(p) + vec3(1,1,1));
float mixLoBack = mySmoothStep(llb, lrb, pFract.x);
float mixHiBack = mySmoothStep(ulb, urb, pFract.x);
float mixLoFront = mySmoothStep(llf, lrf, pFract.x);
float mixHiFront = mySmoothStep(ulf, urf, pFract.x);
float mixLo = mySmoothStep(mixLoBack, mixLoFront, pFract.z);
float mixHi = mySmoothStep(mixHiBack, mixHiFront, pFract.z);
return mySmoothStep(mixLo, mixHi, pFract.y);
}
float fbm(vec3 p) {
float amp = 0.5;
float freq = 4.0;
float sum = 0.0;
for(int i = 0; i < 8; i++) {
sum += cubicTriMix(p * freq) * amp;
amp *= 0.5;
freq *= 2.0;
}
return sum;
}
void main()
{
vec4 diffuseColor = texture(textureSampler, fs_UVs);
bool apply_lambert = true;
float specularIntensity = 0;
if (fs_Anim != 0) {
// check region in texture to decide which animatable type is drawn
bool lava = fs_UVs.x >= 13.f/16.f && fs_UVs.y < 2.f/16.f;
bool water = !lava && fs_UVs.x >= 13.f/16.f && fs_UVs.y < 4.f/16.f;
if (lava) {
// slowly gyrate texture and lighten and darken with random dimVal from vert shader
vec2 movingUVs = vec2(fs_UVs.x + fs_Anim * 0.065/16 * sin(0.01*u_Time),
fs_UVs.y - fs_Anim * 0.065/16 * sin(0.01*u_Time + 3.14159/2));
diffuseColor = texture(textureSampler, movingUVs);
vec4 warmerColor = diffuseColor + vec4(0.3, 0.3, 0, 0);
vec4 coolerColor = diffuseColor - vec4(0.1, 0.1, 0, 0);
diffuseColor = mix(warmerColor, coolerColor, 0.5 + fs_dimVal * 0.65*sin(0.02*u_Time));
apply_lambert = false;
} else if (water) {
// blend between 3 different points in texture to create a wavy subtle change over time
vec2 offsetUVs = vec2(fs_UVs.x - 0.5f/16.f, fs_UVs.y - 0.5f/16.f);
diffuseColor = texture(textureSampler, fs_UVs);
vec4 altColor = texture(textureSampler, offsetUVs);
altColor.x += fs_dimVal * pow(altColor.x+.15, 5);
altColor.y += fs_dimVal * pow(altColor.y+.15, 5);
altColor.z += 0.5 * fs_dimVal * pow(altColor.z+.15, 5);
diffuseColor = mix(diffuseColor, altColor, 0.5 + 0.35*sin(0.05*u_Time));
offsetUVs -= 0.25f/16.f;
vec4 newColor = texture(textureSampler, offsetUVs);
diffuseColor = mix(diffuseColor, newColor, 0.5 + 0.5*sin(0.025*u_Time)) + fs_dimVal * vec4(0.025);
diffuseColor.a = 0.7;
// ----------------------------------------------------
// Blinn-Phong Shading
// ----------------------------------------------------
vec4 lightDir = normalize(fs_LightVec - fs_Pos);
vec4 viewDir = normalize(fs_CamPos - fs_Pos);
vec4 halfVec = normalize(lightDir + viewDir);
float shininess = 400.f;
float specularIntensity = max(pow(dot(halfVec, normalize(fs_Nor)), shininess), 0);
}
}
// Calculate the diffuse term for Lambert shading
float diffuseTerm = dot(normalize(fs_Nor), normalize(fs_LightVec));
// Avoid negative lighting values
diffuseTerm = clamp(diffuseTerm, 0, 1);
float ambientTerm = 0.3;
float lightIntensity = diffuseTerm + ambientTerm; //Add a small float value to the color multiplier
//to simulate ambient lighting. This ensures that faces that are not
//lit by our point light are not completely black.
vec3 col = diffuseColor.rgb;
// Compute final shaded color
if (apply_lambert) {
col = col * lightIntensity + col * specularIntensity;
}
// & Check the rare, special case where we draw face between two diff transparent blocks as opaque
if (fs_T2O != 0) {
out_Col = vec4(col, 1.f);
} else {
out_Col = vec4(col, diffuseColor.a);
}
// distance fog!
vec4 fogColor = vec4(0.6, 0.75, 0.9, 1.0);
float FC = gl_FragCoord.z / gl_FragCoord.w / 124.f;
float falloff = clamp(1.05 - exp(-1.05f * (FC - 0.9f)), 0.f, 1.f);
out_Col = mix(out_Col, fogColor, falloff);
}
I tried implementing blinn-phong in the fragment shader, but I think it is wrong simple from the wrong normals. I think this can be done with some sort of tangent and cross product solution, but how can I know the tangent of the surface given we only know the vertex position?
I am not using unity, just bare c++ and most of the answers I am finding online are for java or unity which I do not understand.`

How to compute vertex normals for a triangle mesh in OpenGl?

To give background, I'm currently generating a surface of revolution with it's center of mass centered at (0,0,0) in the WCS. The surface of a revolution is y=x^2 where 0 <= x <= 1.
I have converted this surface of revolution into a virtual buffer object, and can render it successfully on the screen. However, I cannot seem to get Blinn-Phong shading to work on the object. I'm fairly sure that the problem lies in my normal calculation.
This is the stub that creates the object and calculates normals:
GLfloat vp[49 * 49 * 18]; // array of vertex points
int _i = 50;
int _j = 50;
float vertices[50][50][3];
for (int i = 0; i < _i; i++) {
float fT = (float) i / (_i - 1);
float fY = fT;
float fZ = sqrt(fT);
for (int j = 0; j < _j; j++) {
float fS = 2 * M_PI * (float) j / (_j - 1);
vertices[i][j][0] = fZ * cos(fS);
vertices[i][j][1] = fY - 0.5; // offset by 0.5 to make center of mass the center
vertices[i][j][2] = fZ * sin(fS);
}
}
int curr = 0;
for (int i = 0; i < _i - 1; i++) {
for (int j = 0; j < _j - 1; j++) {
vp[curr++] = vertices[i][j][0];
vp[curr++] = vertices[i][j][1];
vp[curr++] = vertices[i][j][2];
vp[curr++] = vertices[i+1][j][0];
vp[curr++] = vertices[i+1][j][1];
vp[curr++] = vertices[i+1][j][2];
vp[curr++] = vertices[i][j+1][0];
vp[curr++] = vertices[i][j+1][1];
vp[curr++] = vertices[i][j+1][2];
vp[curr++] = vertices[i+1][j][0];
vp[curr++] = vertices[i+1][j][1];
vp[curr++] = vertices[i+1][j][2];
vp[curr++] = vertices[i+1][j+1][0];
vp[curr++] = vertices[i+1][j+1][1];
vp[curr++] = vertices[i+1][j+1][2];
vp[curr++] = vertices[i][j+1][0];
vp[curr++] = vertices[i][j+1][1];
vp[curr++] = vertices[i][j+1][2];
}
}
GLuint vao;
glGenVertexArrays (1, &vao); // generating and binding is common pattern in OpenGL
glBindVertexArray (vao); // basically setting up memory and associating it
GLuint points_vbo;
glGenBuffers(1, &points_vbo);
glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
glBufferData(GL_ARRAY_BUFFER, 49 * 49 * 18 * sizeof (GLfloat), vp, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
GLfloat normals[49 * 49 * 18 / 3];
curr = 0;
for (int i = 0; i < 49 * 49 * 18; i += 9){
int Ux = vp[i+3] - vp[i];
int Uy = vp[i+4] - vp[i+1];
int Uz = vp[i+5] - vp[i+2];
int Vx = vp[i+6] - vp[i];
int Vy = vp[i+7] - vp[i+1];
int Vz = vp[i+8] - vp[i+2];
normals[curr++] = Uy * Vz - Uz * Vy;
normals[curr++] = Uz * Vx - Ux * Vz;
normals[curr++] = Ux * Vy - Uy * Vx;
}
GLuint normals_vbo;
glGenBuffers(1, &normals_vbo);
glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
glBufferData(GL_ARRAY_BUFFER, 49 * 49 * 18 / 3 * sizeof(GLfloat), normals, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(1);
This is my vertex shader:
#version 410
layout (location = 0) in vec3 vtxPosition;
layout (location = 1) in vec3 normal;
uniform mat4 proj_mat, view_mat, model_mat;
out vec3 Normal;
out vec3 fpos;
void main () {
gl_Position = proj_mat * view_mat * model_mat * vec4(vtxPosition, 1.0);
fpos = vec3(model_mat * vec4(vtxPosition, 1.0));
Normal = normal;
}
And lastly my fragment shader:
#version 410
// Define INPUTS from fragment shader
//uniform mat4 view_mat;
in vec3 Normal;
in vec3 fpos;
// These come from the VAO for texture coordinates.
in vec2 texture_coords;
// And from the uniform outputs for the textures setup in main.cpp.
uniform sampler2D texture00;
uniform sampler2D texture01;
out vec4 fragment_color; //RGBA color
const vec3 lightPos = vec3(0.0,0.0,5.0);
const vec3 diffColor = vec3(1.0,0.5,0.0);
const vec3 specColor = vec3(1.0,1.0,1.0);
void main () {
vec3 normal = normalize(Normal);
vec3 lightDir = normalize(lightPos - fpos);
float lamb = max(dot(lightDir, normal), 0.0);
float spec = 0.0;
if (lamb > 0.0) {
vec3 refDir = reflect(-lightDir, normal);
vec3 viewDir = normalize(-fpos);
float specAngle = max(dot(refDir, viewDir), 0.0);
spec = pow(specAngle, 4.0);
}
fragment_color = vec4(lamb * diffColor + spec * specColor, 1.0);
}
This is the current rendering of the object:
You have to specify 1 normal attribute for each vertex coordinate. A vertex coordinate and its attributes form a tuple.
Furthermore you have to use the data type float rather than int, for computing the normal vectors:
GLfloat normals[49 * 49 * 18];
curr = 0;
for (int i = 0; i < 49 * 49 * 18; i += 9){
float Ux = vp[i+3] - vp[i];
float Uy = vp[i+4] - vp[i+1];
float Uz = vp[i+5] - vp[i+2];
float Vx = vp[i+6] - vp[i];
float Vy = vp[i+7] - vp[i+1];
float Vz = vp[i+8] - vp[i+2];
float nx = Uy * Vz - Uz * Vy;
float ny = Uz * Vx - Ux * Vz;
float nz = Ux * Vy - Uy * Vx;
for (int j = 0; j < 3; ++j) {
normals[curr++] = nx;
normals[curr++] = ny;
normals[curr++] = nz;
}
}
glBufferData(GL_ARRAY_BUFFER, 49 * 49 * 18 * sizeof(GLfloat), normals, GL_STATIC_DRAW);
I recommend to invert the normal vector of the back faces for a double sided light model:
vec3 normal = normalize(Normal);
vec3 viewDir = normalize(-fpos);
if (dot(normal, viewDir) < 0.0)
normal *= -1.0;
Fragment shader:
#version 410
// Define INPUTS from fragment shader
//uniform mat4 view_mat;
in vec3 Normal;
in vec3 fpos;
// These come from the VAO for texture coordinates.
in vec2 texture_coords;
// And from the uniform outputs for the textures setup in main.cpp.
uniform sampler2D texture00;
uniform sampler2D texture01;
out vec4 fragment_color; //RGBA color
const vec3 lightPos = vec3(0.0,0.0,5.0);
const vec3 diffColor = vec3(1.0,0.5,0.0);
const vec3 specColor = vec3(1.0,1.0,1.0);
void main () {
vec3 normal = normalize(Normal);
vec3 viewDir = normalize(-fpos);
if (dot(normal, viewDir) < 0.0)
normal *= -1.0;
vec3 lightDir = normalize(lightPos - fpos);
float lamb = max(dot(lightDir, normal), 0.0);
float spec = 0.0;
if (lamb > 0.0) {
vec3 refDir = reflect(-lightDir, normal);
float specAngle = max(dot(refDir, viewDir), 0.0);
spec = pow(specAngle, 4.0);
}
fragment_color = vec4(lamb * diffColor + spec * specColor, 1.0);
}

Point light Dual-paraboloid VSM in deferred rendering

I've been following this tutorial to implement my variance shadow mapping feature for point light in deferred rendering.
I'm using GLSL 3.3, left-handed coordinate system. Here is what I've been doing:
I render the scene to dual-paraboloid maps, storing depth and depth * depth.
Result:
Above image contains front and back maps. The point light is at the center of scene, you can see where it glows yellow the most.
Then I set up a full-screen shader pass.
I do this by transforming the tutorial code from FX to GLSL.
Author's .fx code:
float4 TexturePS(float3 normalW : TEXCOORD0, float2 tex0 : TEXCOORD1, float3 pos : TEXCOORD2) : COLOR
{
float4 texColor = tex2D(TexS, tex0 * TexScale);
pos = mul(float4(pos, 1.0f), LightView);
float L = length(pos);
float3 P0 = pos / L;
float alpha = .5f + pos.z / LightAttenuation;
P0.z = P0.z + 1;
P0.x = P0.x / P0.z;
P0.y = P0.y / P0.z;
P0.z = L / LightAttenuation;
P0.x = .5f * P0.x + .5f;
P0.y = -.5f * P0.y + .5f;
float3 P1 = pos / L;
P1.z = 1 - P1.z;
P1.x = P1.x / P1.z;
P1.y = P1.y / P1.z;
P1.z = L / LightAttenuation;
P1.x = .5f * P1.x + .5f;
P1.y = -.5f * P1.y + .5f;
float depth;
float mydepth;
float2 moments;
if(alpha >= 0.5f)
{
moments = tex2D(ShadowFrontS, P0.xy).xy;
depth = moments.x;
mydepth = P0.z;
}
else
{
moments = tex2D(ShadowBackS, P1.xy).xy;
depth = moments.x;
mydepth = P1.z;
}
float lit_factor = (mydepth <= moments[0]);
float E_x2 = moments.y;
float Ex_2 = moments.x * moments.x;
float variance = min(max(E_x2 - Ex_2, 0.0) + SHADOW_EPSILON, 1.0);
float m_d = (moments.x - mydepth);
float p = variance / (variance + m_d * m_d); //Chebychev's inequality
texColor.xyz *= max(lit_factor, p + .2f);
return texColor;
}
My translated GLSL code:
void main() {
vec3 in_vertex = texture(scenePosTexture, texCoord).xyz; // get 3D vertex from 2D screen coordinate
vec4 vert = lightViewMat * vec4(in_vertex, 1); // project vertex to point light space (view from light position, look target is -Z)
float L = length(vert.xyz);
float distance = length(lightPos - in_vertex);
float denom = distance / lightRad + 1;
float attenuation = 1.0 / (denom * denom);
// to determine which paraboloid map to use
float alpha = vert.z / attenuation + 0.5f;
vec3 P0 = vert.xyz / L;
P0.z = P0.z + 1;
P0.x = P0.x / P0.z;
P0.y = P0.y / P0.z;
P0.z = L / attenuation;
P0.x = .5f * P0.x + .5f;
P0.y = -.5f * P0.y + .5f;
vec3 P1 = vert.xyz / L;
P1.z = 1 - P1.z;
P1.x = P1.x / P1.z;
P1.y = P1.y / P1.z;
P1.z = L / attenuation;
P1.x = .5f * P1.x + .5f;
P1.y = -.5f * P1.y + .5f;
// Variance shadow mapping
float depth;
float mydepth;
vec2 moments;
if(alpha >= 0.5f)
{
moments = texture(shadowMapFrontTexture, P0.xy).xy;
depth = moments.x;
mydepth = P0.z;
}
else
{
moments = texture(shadowMapBackTexture, P1.xy).xy;
depth = moments.x;
mydepth = P1.z;
}
// Original .fx code is: float lit_factor = (mydepth <= moments[0]);
// I'm not sure my translated code belew is correct
float lit_factor = 0;
if (mydepth <= moments.x)
lit_factor = mydepth;
else
lit_factor = moments.x;
float E_x2 = moments.y;
float Ex_2 = moments.x * moments.x;
float variance = min(max(E_x2 - Ex_2, 0.0) + SHADOW_EPSILON, 1.0);
float m_d = (moments.x - mydepth);
float p = variance / (variance + m_d * m_d); //Chebychev's inequality
fragColor = texture(sceneTexture, texCoord).rgb; // sample original color
fragColor.rgb *= max(lit_factor, p + .2f);
}
Render result
Right now I'm clueless about where I'm gonna touch to render the shadow correctly. Could someone point it out for me?
Some friend of mine pointed out that the Y component is flipped, that's why shadow looked like up-side down. After adding minus to P0 and P1's Y, it starts to show quite reasonable shadow:
But another problem is the location of shadow is wrong.
Why do you duplicate the paraboloid projection computation ?
You compute it on 'vert', then 'P0' and 'P1', shouldn't you do it only on 'P0' and 'P1' ? (The original code doesn't do this thing on 'pos').
EDIT:
Your lit_factor is wrong, it should be either 0.0 or 1.0.
You could use the step() GLSL intrinsic, in this way :
float lit_factor = step(mydepth, moments[0]);

Custom Minecraft Shader Bugs

I copied some files from a few shaders, and it works out for the most part, but I sometimes get graphical glitches like this where faces of grass blocks are completely transparent:
I believe my gbuffers_terrain.fsh or gbuffers_terrain.vsh is what is causing the problem.
gbuffers_terrain.fsh:
#version 120
#extension GL_ARB_shader_texture_lod : enable
/* DRAWBUFFERS:0247 */
/*
RRe36's Shaders, derived from Chocapic13 v4
Place two leading Slashes in front of the following '#define' lines in order to disable an option.
IMPORTANT: Placing Slashes in front of lines like '#define FILTER_LEVEL 15.0' will cause errors!
*/
//-------- Adjustable Variables --------//
//---- Normal Mapping ----//
#define NORMAL_MAPPING
#define NORMAL_MAP_MAX_ANGLE 1.0
//---- End of Normal Mapping ----//
//---- Parallax Displacement aka. POM ----//
//#define POM
#define POM_MAP_RES 128.0
#define POM_DEPTH (1.0/20.0)
const float MAX_OCCLUSION_DISTANCE = 32.0;
const float MIX_OCCLUSION_DISTANCE = 28.0;
const int MAX_OCCLUSION_POINTS = 12;
//---- End of Parallax Displacement ----//
//---- Lightmaps ----//
#define MIN_LIGHTAMOUNT 0.1 //affect the minecraft lightmap (not torches)
#define MINELIGHTMAP_EXP 2.0 //affect the minecraft lightmap (not torches)
//---- End of Lightmaps ----//
//-------- End of Adjustable Variables --------//
/* Here, intervalMult might need to be tweaked per texture pack.
The first two numbers determine how many samples are taken per fragment. They should always be the equal to eachother.
The third number divided by one of the first two numbers is inversely proportional to the range of the height-map. */
const vec3 intervalMult = vec3(1.0, 1.0, 1.0/POM_DEPTH)/POM_MAP_RES * 1.0;
const int RGBA16 = 3;
const int RGB16 = 2;
const int RGB8 = 1;
const int gnormalFormat = RGB16;
const int compositeFormat = RGBA16;
const int gaux2Format = RGBA16;
const int gcolorFormat = RGB8;
const int GL_EXP = 2048;
const int GL_LINEAR = 9729;
const float bump_distance = 64.0; //bump render distance: tiny = 32, short = 64, normal = 128, far = 256
const float pom_distance = 32.0; //POM render distance: tiny = 32, short = 64, normal = 128, far = 256
const float fademult = 0.1;
varying vec2 lmcoord;
varying vec4 color;
varying float translucent;
varying vec4 vtexcoordam; // .st for add, .pq for mul
varying vec4 vtexcoord;
varying float dist;
varying vec3 tangent;
varying vec3 normal;
varying vec3 binormal;
varying vec3 viewVector;
uniform sampler2D texture;
uniform sampler2D normals;
uniform sampler2D specular;
uniform vec3 sunPosition;
uniform vec3 moonPosition;
uniform int fogMode;
uniform int worldTime;
uniform float wetness;
uniform float rainStrength;
float totalspec = 0.0;
float wetx = clamp(wetness, 0.0f, 1.0)/1.0;
const float mincoord = 1.0/4096.0;
const float maxcoord = 1.0-mincoord;
vec2 dcdx = dFdx(vtexcoord.st*vtexcoordam.pq);
vec2 dcdy = dFdy(vtexcoord.st*vtexcoordam.pq);
vec4 readTexture(in vec2 coord){
return texture2DGradARB(texture,fract(coord)*vtexcoordam.pq+vtexcoordam.st,dcdx,dcdy);
}
vec4 readNormal(in vec2 coord){
return texture2DGradARB(normals,fract(coord)*vtexcoordam.pq+vtexcoordam.st,dcdx,dcdy);
}
float normalmap_intensity = NORMAL_MAP_MAX_ANGLE-((NORMAL_MAP_MAX_ANGLE*rainStrength)*0.95);
//////////////////////////////main//////////////////////////////
//////////////////////////////main//////////////////////////////
//////////////////////////////main//////////////////////////////
//////////////////////////////main//////////////////////////////
//////////////////////////////main//////////////////////////////
void main() {
vec2 adjustedTexCoord = vtexcoord.st*vtexcoordam.pq+vtexcoordam.st;
#ifdef POM
if (dist < MAX_OCCLUSION_DISTANCE) {
if ( viewVector.z < 0.0 && readNormal(vtexcoord.st).a < 0.99 && readNormal(vtexcoord.st).a > 0.01)
{
vec3 interval = viewVector.xyz * intervalMult;
vec3 coord = vec3(vtexcoord.st, 1.0);
for (int loopCount = 0;
(loopCount < MAX_OCCLUSION_POINTS) && (readNormal(coord.st).a < coord.p);
++loopCount) {
coord = coord+interval;
}
// Don't wrap around top of tall grass/flower
if (coord.t < mincoord) {
if (readTexture(vec2(coord.s,mincoord)).a == 0.0) {
coord.t = mincoord;
discard;
}
}
adjustedTexCoord = mix(fract(coord.st)*vtexcoordam.pq+vtexcoordam.st , adjustedTexCoord , max(dist-MIX_OCCLUSION_DISTANCE,0.0)/(MAX_OCCLUSION_DISTANCE-MIX_OCCLUSION_DISTANCE));
}
}
#endif
vec3 lightVector;
vec3 specularity = texture2DGradARB(specular, adjustedTexCoord.st, dcdx, dcdy).rgb;
float atten = 1.0-(specularity.b)*0.86;
vec4 frag2 = vec4(normal, 1.0f);
vec3 bump = texture2DGradARB(normals, adjustedTexCoord.st, dcdx, dcdy).rgb*2.0-1.0;
float bumpmult = normalmap_intensity*(1.0-wetness*lmcoord.t*0.65)*atten;
bump = bump * vec3(bumpmult, bumpmult, bumpmult) + vec3(0.0f, 0.0f, 1.0f - bumpmult);
mat3 tbnMatrix = mat3(tangent.x, binormal.x, normal.x,
tangent.y, binormal.y, normal.y,
tangent.z, binormal.z, normal.z);
frag2 = vec4(normalize(bump * tbnMatrix) * 0.5 + 0.5, 1.0);
float dirtest = 0.4;
if (worldTime < 12700 || worldTime > 23250) {
lightVector = normalize(sunPosition);
}
else {
lightVector = normalize(moonPosition);
}
dirtest = mix(1.0-0.8*step(dot(frag2.xyz*2.0-1.0,lightVector),-0.02),0.4,float(translucent > 0.01));
/* DRAWBUFFERS:0246 */
gl_FragData[0] = texture2DGradARB(texture, adjustedTexCoord.st, dcdx, dcdy) * color;
gl_FragData[1] = frag2;
gl_FragData[2] = vec4(lmcoord.t, dirtest, lmcoord.s, 1.0);
gl_FragData[3] = texture2DGradARB(specular, adjustedTexCoord.st, dcdx, dcdy);
}
My gbuffers_terrain.vsh:
#version 120
/*
RRe36's Shaders, derived from Chocapic13 v4
Place two leading Slashes in front of the following '#define' lines in order to disable an option.
IMPORTANT: Placing Slashes in front of lines like '#define FILTER_LEVEL 15.0' will cause errors!
*/
//-------- Adjustable Variables --------//
//---- Waving Effects ----//
#define WAVING_LEAVES
#define WAVING_VINES
#define WAVING_GRASS
#define WAVING_WHEAT
#define WAVING_FLOWERS
#define WAVING_FIRE
#define WAVING_LAVA
#define WAVING_LILYPAD
#define WAVING_TALLGRASS
#define WAVING_REEDS
//---- End of Waving Effects ----//
//---- Entity IDs ----//
#define ENTITY_LEAVES 18.0
#define ENTITY_VINES 106.0
#define ENTITY_TALLGRASS 31.0
#define ENTITY_DANDELION 37.0
#define ENTITY_ROSE 38.0
#define ENTITY_WHEAT 59.0
#define ENTITY_LILYPAD 111.0
#define ENTITY_FIRE 51.0
#define ENTITY_LAVAFLOWING 10.0
#define ENTITY_LAVASTILL 11.0
#define ENTITY_SAPLING 6.0
//---- End of Entity IDs ----//
//---- World Effects -----//
//#define WORLD_CURVATURE // will cause bug at high shadowdistances: looks like a dark circle around you
const float WORLD_RADIUS = 6000.0; //Increase for a stronger rounded world
const float WORLD_RADIUS_SQUARED = 15000000.0;
//---- End of World Effects ----//
//-------- End of Adjustable Variables --------//
const float PI = 3.1415927;
varying vec4 color;
varying vec2 lmcoord;
varying float translucent;
varying vec4 vtexcoordam; // .st for add, .pq for mul
varying vec4 vtexcoord;
varying float dist;
varying vec3 tangent;
varying vec3 normal;
varying vec3 binormal;
varying vec3 viewVector;
attribute vec4 mc_Entity;
attribute vec4 mc_midTexCoord;
uniform vec3 cameraPosition;
uniform mat4 gbufferModelView;
uniform mat4 gbufferModelViewInverse;
uniform int worldTime;
uniform float frameTimeCounter;
uniform float rainStrength;
float timefract = worldTime;
//Calculate Time of Day
float TimeSunrise = ((clamp(timefract, 23000.0, 24000.0) - 23000.0) / 1000.0) + (1.0 - (clamp(timefract, 0.0, 4000.0)/4000.0));
float TimeNoon = ((clamp(timefract, 0.0, 4000.0)) / 4000.0) - ((clamp(timefract, 8000.0, 12000.0) - 8000.0) / 4000.0);
float TimeSunset = ((clamp(timefract, 8000.0, 12000.0) - 8000.0) / 4000.0) - ((clamp(timefract, 12000.0, 12750.0) - 12000.0) / 750.0);
float TimeMidnight = ((clamp(timefract, 12000.0, 12750.0) - 12000.0) / 750.0) - ((clamp(timefract, 23000.0, 24000.0) - 23000.0) / 1000.0);
float animationTime = worldTime/20.0f;
float pi2wt = PI*2*(frameTimeCounter*24 + (rainStrength*2));
vec3 calcWave(in vec3 pos, in float fm, in float mm, in float ma, in float f0, in float f1, in float f2, in float f3, in float f4, in float f5) {
vec3 ret;
float magnitude,d0,d1,d2,d3;
magnitude = sin(pi2wt*fm + pos.x*0.5 + pos.z*0.5 + pos.y*0.5) * mm + ma;
d0 = sin(pi2wt*f0)*(rainStrength*2);
d1 = sin(pi2wt*f1)*(rainStrength*1.75);
d2 = sin(pi2wt*f2)*(rainStrength*1.5);
ret.x = sin(pi2wt*f3 + d0 + d1 - pos.x + pos.z + pos.y) * magnitude;
ret.z = sin(pi2wt*f4 + d1 + d2 + pos.x - pos.z + pos.y) * magnitude;
ret.y = sin(pi2wt*f5 + d2 + d0 + pos.z + pos.y - pos.y) * magnitude;
return ret;
}
vec3 calcMove(in vec3 pos, in float f0, in float f1, in float f2, in float f3, in float f4, in float f5, in vec3 amp1, in vec3 amp2) {
vec3 move1 = calcWave(pos , 0.0027, 0.0400, 0.0400, 0.0127, 0.0089, 0.0114, 0.0063, 0.0224, 0.0015) * amp1;
vec3 move2 = calcWave(pos+move1, 0.0348, 0.0400, 0.0400, f0, f1, f2, f3, f4, f5) * amp2;
return move1+move2;
}
vec3 calcWaterMove(in vec3 pos) {
float fy = fract(pos.y + 0.001);
if (fy > 0.002) {
float wave = 0.05 * sin(2 * PI * (worldTime / 86.0 + pos.x / 7.0 + pos.z / 13.0))
+ 0.05 * sin(2 * PI * (worldTime / 60.0 + pos.x / 11.0 + pos.z / 5.0));
return vec3(0, clamp(wave, -fy, 1.0-fy), 0);
}
else {
return vec3(0);
}
}
//////////////////////////////main//////////////////////////////
//////////////////////////////main//////////////////////////////
//////////////////////////////main//////////////////////////////
//////////////////////////////main//////////////////////////////
//////////////////////////////main//////////////////////////////
void main() {
vec2 texcoord = (gl_TextureMatrix[0] * gl_MultiTexCoord0).st;
vec2 midcoord = (gl_TextureMatrix[0] * mc_midTexCoord).st;
vec2 texcoordminusmid = texcoord-midcoord;
vtexcoordam.pq = abs(texcoordminusmid)*2;
vtexcoordam.st = min(texcoord,midcoord-texcoordminusmid);
vtexcoord.st = sign(texcoordminusmid)*0.5+0.5;
translucent = 0.0f;
float istopv = 0.0;
if (gl_MultiTexCoord0.t < mc_midTexCoord.t) istopv = 1.0;
/* un-rotate */
vec4 position = gbufferModelViewInverse * gl_ModelViewMatrix * gl_Vertex;
vec3 worldpos = position.xyz + cameraPosition;
//initialize per-entity waving parameters
float parm0,parm1,parm2,parm3,parm4,parm5 = rainStrength*4;
vec3 ampl1,ampl2;
ampl1 = vec3(0.0);
ampl2 = vec3(0.0);
#ifdef WAVING_LEAVES
if (( mc_Entity.x == ENTITY_LEAVES || mc_Entity.x == 161 )) {
parm0 = 0.0040;
parm1 = 0.0064;
parm2 = 0.0043;
parm3 = 0.0035;
parm4 = 0.0037;
parm5 = 0.0041;
ampl1 = vec3(1.0,0.2,1.0) + rainStrength/4;
ampl2 = vec3(0.5,0.1,0.5) + rainStrength/4;
}
#endif
#ifdef WAVING_VINES
if ( mc_Entity.x == ENTITY_VINES ) {
parm0 = 0.0040;
parm1 = 0.0064;
parm2 = 0.0043;
parm3 = 0.0035;
parm4 = 0.0037;
parm5 = 0.0041;
ampl1 = vec3(1.0,0.2,1.0);
ampl2 = vec3(0.5,0.1,0.5);
}
#endif
#ifdef WAVING_REEDS
if ( mc_Entity.x == 83 ) {
parm0 = 0.0024;
parm1 = 0.0020;
parm2 = 0.0016;
parm3 = 0.0010;
parm4 = 0.0009;
parm5 = 0.0002;
ampl1 = vec3(0.25,0.05,0.25) + rainStrength/5;
ampl2 = vec3(0.125,0.025,0.125) + rainStrength/5;
}
#endif
if (istopv > 0.9) {
#ifdef WAVING_GRASS
if ( mc_Entity.x == ENTITY_TALLGRASS || mc_Entity.x == ENTITY_SAPLING) {
parm0 = 0.0041;
parm1 = 0.0070;
parm2 = 0.0044;
parm3 = 0.0038;
parm4 = 0.0063;
parm5 = 0.0;
ampl1 = vec3(0.8,0.0,0.8) + 0.2 + rainStrength/3;
ampl2 = vec3(0.4,0.0,0.4) + 0.2 + rainStrength/3;
}
#endif
#ifdef WAVING_FLOWERS
if ((mc_Entity.x == ENTITY_DANDELION || mc_Entity.x == ENTITY_ROSE)) {
parm0 = 0.0041;
parm1 = 0.005;
parm2 = 0.0044;
parm3 = 0.0038;
parm4 = 0.0240;
parm5 = 0.0;
ampl1 = vec3(0.8,0.0,0.8) + rainStrength/3;
ampl2 = vec3(0.4,0.0,0.4) + rainStrength/3;
}
#endif
#ifdef WAVING_WHEAT
if ( mc_Entity.x == ENTITY_WHEAT || mc_Entity.x == 141 || mc_Entity.x == 142) {
parm0 = 0.0041;
parm1 = 0.0070;
parm2 = 0.0044;
parm3 = 0.0240;
parm4 = 0.0063;
parm5 = 0.0;
ampl1 = vec3(0.6,0.0,0.8) + rainStrength/3;
ampl2 = vec3(0.4,0.0,0.5) + rainStrength/3;
}
#endif
#ifdef WAVING_FIRE
if ( mc_Entity.x == ENTITY_FIRE) {
parm0 = 0.0105;
parm1 = 0.0096;
parm2 = 0.0087;
parm3 = 0.0063;
parm4 = 0.0097;
parm5 = 0.0156;
ampl1 = vec3(1.2,0.4,1.2) + rainStrength*1.8;
ampl2 = vec3(0.8,0.8,0.8) + rainStrength*1.8;
}
#endif
}
float movemult = 0.0;
#ifdef WAVING_LAVA
if ( mc_Entity.x == ENTITY_LAVAFLOWING || mc_Entity.x == ENTITY_LAVASTILL ) movemult = 0.25;
#endif
#ifdef WAVING_LILYPAD
if ( mc_Entity.x == ENTITY_LILYPAD ) movemult = 1.0 + (rainStrength*0.5);
#endif
#ifdef WAVING_TALLGRASS
if ( mc_Entity.x == 175) {
parm0 = 0.0031;
parm1 = 0.004;
parm2 = 0.0034;
parm3 = 0.0028;
parm4 = 0.0163;
parm5 = 0.0;
ampl1 = vec3(0.4,0.0,0.4);
ampl2 = vec3(0.2,0.0,0.2);
}
#endif
#ifdef WORLD_CURVATURE
if (gl_Color.a != 0.8) {
float distanceSquared = position.x * position.x + position.z * position.z;
position.y -= WORLD_RADIUS - sqrt(max(1.0 - distanceSquared / WORLD_RADIUS_SQUARED, 0.0)) * WORLD_RADIUS;
}
#endif
position.xyz += calcWaterMove(worldpos.xyz) * movemult;
position.xyz += calcMove(worldpos.xyz, parm0, parm1, parm2, parm3, parm4, parm5, ampl1, ampl2);
if ( mc_Entity.x == 37 || mc_Entity.x == 31 || mc_Entity.x == 175 || mc_Entity.x == 59 || mc_Entity.x == 141 || mc_Entity.x == 142 || mc_Entity.x == 31 )
translucent = 1.0;
/* re-rotate */
/* projectify */
gl_Position = gl_ProjectionMatrix * gbufferModelView * position;
color = gl_Color;
lmcoord = (gl_TextureMatrix[1] * gl_MultiTexCoord1).xy;
normal = normalize(gl_NormalMatrix * gl_Normal);
tangent = vec3(0.0);
binormal = vec3(0.0);
normal = normalize(gl_NormalMatrix * gl_Normal);
if (gl_Normal.x > 0.5) {
// 1.0, 0.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
} else if (gl_Normal.x < -0.5) {
// -1.0, 0.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
} else if (gl_Normal.y > 0.5) {
// 0.0, 1.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
} else if (gl_Normal.y < -0.5) {
// 0.0, -1.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
} else if (gl_Normal.z > 0.5) {
// 0.0, 0.0, 1.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
} else if (gl_Normal.z < -0.5) {
// 0.0, 0.0, -1.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
}
mat3 tbnMatrix = mat3(tangent.x, binormal.x, normal.x,
tangent.y, binormal.y, normal.y,
tangent.z, binormal.z, normal.z);
viewVector = ( gl_ModelViewMatrix * gl_Vertex).xyz;
viewVector = normalize(tbnMatrix * viewVector);
dist = 0.0;
dist = length(gbufferModelView *gbufferModelViewInverse * gl_ModelViewMatrix * gl_Vertex);
}
My composite.fsh:
#version 120
//------------------------------------
//datLax' OnlyWater v2.0
//
//If you have questions, suggestions or bugs you want to report, please comment on my minecraftforum.net thread:
//http://www.minecraftforum.net/forums/mapping-and-modding/minecraft-mods/2381727-shader-pack-datlax-onlywater-only-water
//
//This code is free to use,
//but don't forget to give credits! :)
//------------------------------------
uniform sampler2D gcolor;
uniform sampler2D depthtex0;
uniform sampler2D gaux1;
varying vec4 texcoord;
varying vec3 ambient_color;
varying float TimeMidnight;
uniform int worldTime;
uniform mat4 gbufferProjection;
uniform mat4 gbufferProjectionInverse;
uniform mat4 gbufferModelViewInverse;
uniform float near;
uniform float far;
uniform float viewWidth;
uniform float viewHeight;
float ld(float depth) {
return (2.0 * near) / (far + near - depth * (far - near));
}
vec3 aux = texture2D(gaux1, texcoord.st).rgb;
float land = aux.b;
float torch_lightmap = aux.b;
float sky_lightmap = aux.g;
float landx = 1.0-step(land, 0.01);
float iswater = 0.0;
float pixeldepth = texture2D(depthtex0,texcoord.xy).x;
float pw = 1.0/ viewWidth;
float ph = 1.0/ viewHeight;
float callwaves(vec2 pos) {
float wsize = 2.9;
float wspeed = 0.025f;
float rs0 = abs(sin((worldTime*wspeed/5.0) + (pos.s*wsize) * 20.0)+0.2);
float rs1 = abs(sin((worldTime*wspeed/7.0) + (pos.t*wsize) * 27.0));
float rs2 = abs(sin((worldTime*wspeed/2.0) + (pos.t*wsize) * 60.0 - sin(pos.s*wsize) * 13.0)+0.4);
float rs3 = abs(sin((worldTime*wspeed/1.0) - (pos.s*wsize) * 20.0 + cos(pos.t*wsize) * 83.0)+0.1);
float wsize2 = 1.7;
float wspeed2 = 0.017f;
float rs0a = abs(sin((worldTime*wspeed2/4.0) + (pos.s*wsize2) * 24.0));
float rs1a = abs(sin((worldTime*wspeed2/11.0) + (pos.t*wsize2) * 77.0 )+0.3);
float rs2a = abs(sin((worldTime*wspeed2/6.0) + (pos.s*wsize2) * 50.0 - (pos.t*wsize2) * 23.0)+0.12);
float rs3a = abs(sin((worldTime*wspeed2/14.0) - (pos.t*wsize2) * 4.0 + (pos.s*wsize2) * 98.0));
float wsize3 = 0.3;
float wspeed3 = 0.03f;
float rs0b = abs(sin((worldTime*wspeed3/4.0) + (pos.s*wsize3) * 14.0));
float rs1b = abs(sin((worldTime*wspeed3/11.0) + (pos.t*wsize3) * 37.0));
float rs2b = abs(sin((worldTime*wspeed3/6.0) + (pos.t*wsize3) * 47.0 - cos(pos.s*wsize3) * 33.0 + rs0a + rs0b));
float rs3b = abs(sin((worldTime*wspeed3/14.0) - (pos.s*wsize3) * 13.0 + sin(pos.t*wsize3) * 98.0 + rs0 + rs1));
float waves = (rs1 * rs0 + rs2 * rs3)/2.0f;
float waves2 = (rs0a * rs1a + rs2a * rs3a)/2.0f;
float waves3 = (rs0b + rs1b + rs2b + rs3b)*0.25;
return (waves + waves2 + waves3)/3.0f;
}
//----------------MAIN------------------
void main() {
if(aux.g > 0.01 && aux.g < 0.07) {
iswater = 1.0;
}
vec4 fragposition = gbufferProjectionInverse * vec4(texcoord.s * 2.0f - 1.0f, texcoord.t * 2.0f - 1.0f, 2.0f * pixeldepth - 1.0f, 1.0f);
fragposition /= fragposition.w;
float dist = length(fragposition.xyz);
vec4 worldposition = vec4(0.0);
worldposition = gbufferModelViewInverse * fragposition;
vec3 color = texture2D(gcolor, texcoord.st).rgb;
const float rspread = 0.30f;
float wave = 0.0;
if (iswater == 1.0) {
wave = callwaves(worldposition.xz*0.02)*2.0-1.0;
wave = wave;
const float wnormalclamp = 0.05f;
float rdepth = pixeldepth;
float waves = wave;
float wnormal_x1 = texture2D(depthtex0, texcoord.st + vec2(pw, 0.0f)).x - texture2D(depthtex0, texcoord.st).x;
float wnormal_x2 = texture2D(depthtex0, texcoord.st).x - texture2D(depthtex0, texcoord.st + vec2(-pw, 0.0f)).x;
float wnormal_x = 0.0f;
if(abs(wnormal_x1) > abs(wnormal_x2)){
wnormal_x = wnormal_x2;
} else {
wnormal_x = wnormal_x1;
}
wnormal_x /= 1.0f - rdepth;
wnormal_x = clamp(wnormal_x, -wnormalclamp, wnormalclamp);
wnormal_x *= rspread;
float wnormal_y1 = texture2D(depthtex0, texcoord.st + vec2(0.0f, ph)).x - texture2D(depthtex0, texcoord.st).x;
float wnormal_y2 = texture2D(depthtex0, texcoord.st).x - texture2D(depthtex0, texcoord.st + vec2(0.0f, -ph)).x;
float wnormal_y;
if(abs(wnormal_y1) > abs(wnormal_y2)){
wnormal_y = wnormal_y2;
} else {
wnormal_y = wnormal_y1;
}
wnormal_y /= 1.0f - rdepth;
wnormal_y = clamp(wnormal_y, -wnormalclamp, wnormalclamp);
wnormal_y *= rspread;
//Calculate distance of objects behind water
float refractdist = 0.2 * 10.0f;
//Perform refraction
float refractamount = 500.1154f*0.35f*refractdist;
float refractamount2 = 0.0214f*0.05f*refractdist;
float refractamount3 = 0.214f*0.15f*refractdist;
float waberration = 0.105;
vec3 refracted = vec3(0.0f);
float refractedmask = 0.0;
float bigWaveRefract = 0.0;
float bigWaveRefractScale = 0.0;
vec2 bigRefract = vec2(wnormal_x*bigWaveRefract, wnormal_y*bigWaveRefract);
vec2 refractcoord_r = texcoord.st;
vec2 refractcoord_g = texcoord.st;
vec2 refractcoord_b = texcoord.st;
for (int i = 0; i < 1; ++i) {
refractcoord_r = texcoord.st * (1.0f + waves*refractamount3) - (waves*refractamount3/2.0f) + vec2( waves*refractamount2 + (-wnormal_x*0.4f) - bigRefract.x, waves*refractamount2 + (-wnormal_y*0.4f) - bigRefract.y) * (waberration * 2.0f + 1.0f);
refractcoord_r = refractcoord_r * vec2(1.0f - abs(wnormal_x) * bigWaveRefractScale, 1.0f - abs(wnormal_y) * bigWaveRefractScale) + vec2(abs(wnormal_x) * bigWaveRefractScale * 0.5f, abs(wnormal_y) * bigWaveRefractScale * 0.5f);
refractcoord_r.s = clamp(refractcoord_r.s, 0.001f, 0.999f);
refractcoord_r.t = clamp(refractcoord_r.t, 0.001f, 0.999f);
if (refractcoord_r.s > 1.0 || refractcoord_r.s < 0.0 || refractcoord_r.t > 1.0 || refractcoord_r.t < 0.0) {
break;
}
refracted.rgb = texture2D(gcolor, refractcoord_r).rgb;
refractedmask = texture2D(gaux1, refractcoord_r).g;
if(refractedmask > 0.01 && refractedmask < 0.07) {
refractedmask = 1.0;
}else refractedmask = 0.0;
}
color.rgb = mix(color.rgb, refracted.rgb, vec3(refractedmask));
}
wave = wave*0.5+0.5;
if (iswater > 0.9){
wave += 0.02;
}else{
wave = 0.0;
}
if (landx == 1.0) {
//vec3 torchcolor = vec3(1.0, 0.675, 0.415);
vec3 torchcolor = vec3(0.8, 0.7, 0.3);
vec3 torchlight_lightmap = torch_lightmap * torchcolor;
color = color * torchlight_lightmap * TimeMidnight + color * ambient_color;
}
/* DRAWBUFFERS:3 */
gl_FragData[0] = vec4(color, 1.0);
/* DRAWBUFFERS:NNN3N5 */
gl_FragData[5] = vec4(0.0, wave, 0.0, 0.0);
gl_FragData[3] = vec4(color, land);
}
My composite.vsh:
#version 120
//------------------------------------
//datLax' OnlyWater v2.0
//
//If you have questions, suggestions or bugs you want to report, please comment on my minecraftforum.net thread:
//http://www.minecraftforum.net/forums/mapping-and-modding/minecraft-mods/2381727-shader-pack-datlax-onlywater-only-water
//
//This code is free to use,
//but don't forget to give credits! :)
//------------------------------------
varying vec4 texcoord;
varying float TimeMidnight;
varying float TimeSunset;
varying float TimeNoon;
varying float TimeSunrise;
varying vec3 ambient_color;
uniform int worldTime;
void main() {
gl_Position = ftransform();
texcoord = gl_MultiTexCoord0;
float timefract = float(worldTime);
TimeSunrise = ((clamp(timefract, 23000.0, 24000.0) - 23000.0) / 1000.0) + (1.0-(clamp(timefract, 0.0, 6000.0)/6000.0));
TimeNoon = ((clamp(timefract, 0.0, 6000.0)) / 6000.0) - ((clamp(timefract, 6000.0, 12000.0) - 6000.0) / 6000.0);
TimeSunset = ((clamp(timefract, 6000.0, 12000.0) - 6000.0) / 6000.0) - ((clamp(timefract, 12000.0, 12750.0) - 12000.0) / 750.0);
TimeMidnight = ((clamp(timefract, 12000.0, 12750.0) - 12000.0) / 750.0) - ((clamp(timefract, 23000.0, 24000.0) - 23000.0) / 1000.0);
vec3 sunrise_amb;
sunrise_amb.r = TimeSunrise;
sunrise_amb.g = TimeSunrise;
sunrise_amb.b = TimeSunrise;
vec3 noon_amb;
noon_amb.r = TimeNoon;
noon_amb.g = TimeNoon;
noon_amb.b = TimeNoon;
vec3 sunset_amb;
sunset_amb.r = 0.95*TimeSunset;
sunset_amb.g = 0.95*TimeSunset;
sunset_amb.b = 0.95*TimeSunset;
vec3 midnight_amb;
midnight_amb.r = 0.45*TimeMidnight;
midnight_amb.g = 0.45*TimeMidnight;
midnight_amb.b = 0.7*TimeMidnight;
ambient_color.r = sunrise_amb.r + noon_amb.r + sunset_amb.r + midnight_amb.r;
ambient_color.g = sunrise_amb.g + noon_amb.g + sunset_amb.g + midnight_amb.g;
ambient_color.b = sunrise_amb.b + noon_amb.b + sunset_amb.b + midnight_amb.b;
}
I am using a 128x128 resource pack, and I don't know much about shaders. Why are faces of grass blocks flickering, and is there a way to fix this? Also, when recording from OBS screen capture, the video turns out flashing. Reminder: I pulled gbuffers_terrain from a completely different shaderpack.
Specs:
OS: Ubuntu 16.04 LTS 64-bit
RAM: 8GB
CPU: Intel® Core™ i5-4460 CPU # 3.20GHz × 4
GPU: Intel® Haswell Desktop
OpenGL:
OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) Haswell Desktop
OpenGL core profile version string: 3.3 (Core Profile) Mesa 12.1.0-devel
OpenGL core profile shading language version string: 3.30
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 3.0 Mesa 12.1.0-devel
OpenGL shading language version string: 1.30
OpenGL context flags: (none)
OpenGL extensions:
OpenGL ES profile version string: OpenGL ES 3.0 Mesa 12.1.0-devel
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.00
OpenGL ES profile extensions:

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).