问题描述
我正在尝试实现上帝的光芒,但是我不知道哪里出了问题。神射线的来源是立方体的中心。
顶点着色器:
#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);
}
没有Godrays的场景:
添加了上帝射线代码时的片段着色器:
#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,// top right
1.0f,-1.0f,// bottom right
-1.0f,// bottom left
-1.0f,// top left
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,(void*)(3 * sizeof(float)));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,screenTexture);
glDrawArrays(GL_TRIANGLES,6);
shaderProgram.deleteProgram();
glDeleteBuffers(1,&testBuffer);
解决方法
这是解决方案。问题出在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);
}