首页 > 解决方案 > 我的 godRays 片段着色器哪里出错了?

问题描述

我正在尝试实现上帝之光,但我不明白哪里出了问题。神光的来源是立方体的中心。

顶点着色器:

#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;
}  

这是一个简单的片段着色器,只是为了向您展示当我没有在片段着色器中添加上帝光线代码时场景的样子:

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

uniform sampler2D screenTexture;

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

没有神光的场景:

在此处输入图像描述

添加上帝射线代码时的片段着色器:

#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);
}

场景如何处理 godRays 代码:

在此处输入图像描述

此代码用于将立方体中心的坐标从世界转换到窗口空间位置:

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

这就是我设置纹理的方式:

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

标签: c++openglglm-mathrender-to-texturepost-processing

解决方案


这是解决方案。问题出在线路上vec3 color = texture2D(screenTexture, TexCoords);vec3 sample = texture2D(screenTexture, texCoord); 我分别替换了它们 vec3 color = texture(screenTexture, TexCoords).rgb; vec3 sample = texture(screenTexture, texCoord).rgb;

#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);
}

推荐阅读