Elnur
Elnur

Reputation: 119

Where did I make a mistake in my godRays fragment shader?

I am trying to implement god rays however I do not understand where it went wrong. The source of god rays is the center of the cube.

Vertex shader:

#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoords;

out vec2 TexCoords;

void main()
{
    gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); 
    TexCoords = aTexCoords;
}  

This is simple fragment shader just to show you how scene looks like when I did not add code for god rays to the fragment shader:

#version 330 core
out vec4 FragColor;
  
in vec2 TexCoords;

uniform sampler2D screenTexture;

void main()
{ 
    FragColor = texture2D(screenTexture, TexCoords);
}

Scene without godrays:

enter image description here

Fragment shader when god rays code is added:

#version 330 core
out vec4 FragColor;
  
in vec2 TexCoords;

uniform vec2 lightPositionOnScreen;
uniform sampler2D screenTexture;

const float exposure = 0.3f;
const float decay = 0.96815;
const float density  = 0.926;
const float weight  = 0.587;
const int NUM_SAMPLES = 80;

void main()
{ 
    // Calculate vector from pixel to light source in screen space.    
    vec2 deltaTexCoord = (TexCoords - lightPositionOnScreen.xy);   
    vec2 texCoord = TexCoords;

    // Divide by number of samples and scale by control factor.   
    deltaTexCoord *= 1.0f / NUM_SAMPLES * density;   

    // Store initial sample.    
    vec3 color = texture2D(screenTexture, TexCoords);   

    // Set up illumination decay factor.    
    float illuminationDecay = 1.0f;   

    // Evaluate summation from Equation 3 NUM_SAMPLES iterations.    
    for (int i = 0; i < NUM_SAMPLES; i++)   
    {     
        // Step sample location along ray.     
        texCoord -= deltaTexCoord;     

        // Retrieve sample at new location.    
        vec3 sample = texture2D(screenTexture, texCoord);     
    
        // Apply sample attenuation scale/decay factors.     
        sample *= illuminationDecay * weight;     

        // Accumulate combined color.     
        color += sample;     

        // Update exponential decay factor.     
        illuminationDecay *= decay;   
    } 
    
    FragColor  = vec4(color * exposure, 1.0);
}

How scene looks after godRays code:

enter image description here

This code is used to translate coordinates of cube center from world to window space position:

    glm::vec4 clipSpacePos = projection * (view * glm::vec4(m_cubeCenter, 1.0));
    glm::vec3 ndcSpacePos = glm::vec3(clipSpacePos.x / clipSpacePos.w, clipSpacePos.y / clipSpacePos.w, clipSpacePos.z / clipSpacePos.w);
    glm::vec2 windowSpacePos;
    windowSpacePos.x = (ndcSpacePos.x + 1.0) / 2.0;
    windowSpacePos.y = 1.0f - (ndcSpacePos.y + 1.0) / 2.0;
    wxMessageOutputDebug().Printf("test %f x position", windowSpacePos.x);
    wxMessageOutputDebug().Printf("test %f y position", windowSpacePos.y);

    shaderProgram.loadShaders("Shaders/godRays.vert", "Shaders/godRays.frag");
    shaderProgram.use();
    shaderProgram.setUniform("lightPositionOnScreen", windowSpacePos);

This is how I am setting up texture:

    GLfloat vertices[] = {
        1.0f,  1.0f, 0.0f,   1.0f, 1.0f,   // top right
        1.0f, -1.0f, 0.0f,   1.0f, 0.0f,   // bottom right
       -1.0f, -1.0f, 0.0f,   0.0f, 0.0f,   // bottom left
       -1.0f, -1.0f, 0.0f,   0.0f, 0.0f,   // bottom left
       -1.0f,  1.0f, 0.0f,   0.0f, 1.0f,    // top left 
        1.0f,  1.0f, 0.0f,   1.0f, 1.0f,   // top right
    };

    GLuint testBuffer;  

    glGenBuffers(1, &testBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
    glBufferData(GL_ARRAY_BUFFER, 30 * sizeof(GLfloat), &vertices[0], GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), NULL);

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(float)));

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, screenTexture);
    glDrawArrays(GL_TRIANGLES, 0, 6);
    shaderProgram.deleteProgram();
    glDeleteBuffers(1, &testBuffer);

Upvotes: 1

Views: 352

Answers (1)

Elnur
Elnur

Reputation: 119

Here is the solution. The problem was in the lines vec3 color = texture2D(screenTexture, TexCoords); and vec3 sample = texture2D(screenTexture, texCoord); I replaced them with vec3 color = texture(screenTexture, TexCoords).rgb; vec3 sample = texture(screenTexture, texCoord).rgb; respectively.

#version 330 core
out vec4 FragColor;
  
in vec2 TexCoords;

uniform vec2 lightPositionOnScreen;
uniform sampler2D screenTexture;

const float exposure = 0.3f;
const float decay = 0.96815;
const float density  = 0.926;
const float weight  = 0.587;
const int NUM_SAMPLES = 100;

void main()
{ 
    vec2 deltaTexCoord = vec2(TexCoords.xy - lightPositionOnScreen.xy);   
    vec2 texCoord = TexCoords;
 
    deltaTexCoord *= 1.0f / NUM_SAMPLES * density;   

    vec3 color = texture(screenTexture, TexCoords).rgb;   
   
    float illuminationDecay = 1.0f;   
   
    for (int i = 0; i < NUM_SAMPLES; i++)   
    {         
        texCoord -= deltaTexCoord;     
  
        vec3 sample = texture(screenTexture, texCoord).rgb;     
       
        sample *= illuminationDecay * weight;     
   
        color += sample;     
   
        illuminationDecay *= decay;   
    }
    
    FragColor  = vec4(color * exposure, 1.0);
}

Upvotes: 1

Related Questions