Reputation: 119
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:
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:
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
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