3D C/C++ tutorials - OpenGL 2.1 - Sun rays, lens flare, halo
3D C/C++ tutorials -> OpenGL 2.1 -> Sun rays, lens flare, halo
Use for personal or educational purposes only. Commercial and other profit uses strictly prohibited. Exploitation of content on a website or in a publication prohibited.
To compile and run these tutorials some or all of these libraries are required: FreeImage 3.16.0, GLEW 1.11.0, GLUT 3.7.6 / GLUT for Dev-C++, GLM 0.9.5.4
opengl_21_tutorials_win32_framework.h
...

class COpenGLRenderer
{
protected:
    ...

protected:
    CTexture DirtTexture;
    CShaderProgram SunDepthTest, BlurH, BlurV, SunRaysLensFlareHalo;
    GLuint /*ScreenTexture,*/ DepthTexture, SunTextures[5], FBO;
    int SunTextureWidth, SunTextureHeight;

public:
    ...
};

...
opengl_21_tutorials_win32_framework.cpp
...

COpenGLRenderer::COpenGLRenderer()
{
    Camera.SetViewMatrixPointer(&ViewMatrix);
}

COpenGLRenderer::~COpenGLRenderer()
{
}

bool COpenGLRenderer::Init()
{
    bool Error = false;

    if(!GLEW_ARB_texture_non_power_of_two)
    {
        ErrorLog.Append("GL_ARB_texture_non_power_of_two not supported!\r\n");
        Error = true;
    }

    if(!GLEW_ARB_depth_texture)
    {
        ErrorLog.Append("GL_ARB_depth_texture not supported!\r\n");
        Error = true;
    }

    if(!GLEW_EXT_framebuffer_object)
    {
        ErrorLog.Append("GL_EXT_framebuffer_object not supported!\r\n");
        Error = true;
    }

    Error |= !DirtTexture.LoadTexture2D("lensdirt_lowc.jpg");

    Error |= !SunDepthTest.Load("sundepthtest.vs", "sundepthtest.fs");
    Error |= !BlurH.Load("blur.vs", "blurh.fs");
    Error |= !BlurV.Load("blur.vs", "blurv.fs");
    Error |= !SunRaysLensFlareHalo.Load("sunrayslensflarehalo.vs", "sunrayslensflarehalo.fs");

    if(Error)
    {
        return false;
    }

    glUseProgram(SunDepthTest);
    glUniform1i(glGetUniformLocation(SunDepthTest, "SunTexture"), 0);
    glUniform1i(glGetUniformLocation(SunDepthTest, "SunDepthTexture"), 1);
    glUniform1i(glGetUniformLocation(SunDepthTest, "DepthTexture"), 2);
    glUseProgram(0);

    glUseProgram(SunRaysLensFlareHalo);
    glUniform1i(glGetUniformLocation(SunRaysLensFlareHalo, "LowBlurredSunTexture"), 0);
    glUniform1i(glGetUniformLocation(SunRaysLensFlareHalo, "HighBlurredSunTexture"), 1);
    glUniform1i(glGetUniformLocation(SunRaysLensFlareHalo, "DirtTexture"), 2);
    glUniform1f(glGetUniformLocation(SunRaysLensFlareHalo, "Dispersal"), 0.1875f);
    glUniform1f(glGetUniformLocation(SunRaysLensFlareHalo, "HaloWidth"), 0.45f);
    glUniform1f(glGetUniformLocation(SunRaysLensFlareHalo, "Intensity"), 1.5f);
    glUniform3f(glGetUniformLocation(SunRaysLensFlareHalo, "Distortion"), 0.94f, 0.97f, 1.00f);
    glUseProgram(0);

    //glGenTextures(1, &ScreenTexture);
    glGenTextures(1, &DepthTexture);
    glGenTextures(5, SunTextures);

    glGenFramebuffersEXT(1, &FBO);

    Camera.Look(vec3(0.5f, 0.25f, 2.5f) * 2.5f, vec3(0.0f, 0.0f, 0.0f), true);

    GLfloat LightModelAmbient[] = {0.0f, 0.0f, 0.0f, 1.0f};
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, LightModelAmbient);

    GLfloat LightAmbient[] = {0.25f, 0.25f, 0.25f, 1.0f};
    glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);

    GLfloat LightDiffuse[] = {0.75f, 0.75f, 0.75f, 1.0f};
    glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);

    GLfloat MaterialAmbient[] = {1.0f, 1.0f, 1.0f, 1.0f};
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, MaterialAmbient);

    GLfloat MaterialDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialDiffuse);

    glEnable(GL_LIGHT0);
    glEnable(GL_COLOR_MATERIAL);

    return true;
}

void COpenGLRenderer::Render(float FrameTime)
{
    float SunR = 3.75f;
    vec3 SunPos = /*Camera.Position +*/ vec3(0.0f, 0.0f, -100.0f);

    glViewport(0, 0, Width, Height);
    
    //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
    //glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, ScreenTexture, 0);
    //glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, DepthTexture, 0);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadMatrixf(&ProjectionMatrix);

    glMatrixMode(GL_MODELVIEW);
    glLoadMatrixf(&ViewMatrix);

    glLightfv(GL_LIGHT0, GL_POSITION, &vec4(SunPos, 1.0f));

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    glEnable(GL_LIGHTING);

    glColor3f(1.0f, 1.0f, 1.0f);
    
    GLUquadric *obj = gluNewQuadric();

    for(int z = -2; z <= 2; z += 1)
    {
        for(int x = -2; x <= 2; x += 1)
        {
            glMatrixMode(GL_MODELVIEW);
            glLoadMatrixf(&ViewMatrix);
            glTranslatef((float)x, -0.5f, (float)z);
            gluSphere(obj, 0.25f, 32, 32);
        }
    }

    gluDeleteQuadric(obj);

    glDisable(GL_LIGHTING);
    glDisable(GL_CULL_FACE);
    glDisable(GL_DEPTH_TEST);

    glBindTexture(GL_TEXTURE_2D, DepthTexture);
    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height);
    glBindTexture(GL_TEXTURE_2D, 0);

    //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

    bool CalculateSunRaysLensFlareHalo = false;
    int Test = 0, Tests = 16;
    float Angle = 0.0f, AngleInc = 360.0f / Tests;

    mat4x4 VPB = BiasMatrix * ProjectionMatrix * ViewMatrix;

    while(Test < Tests && !CalculateSunRaysLensFlareHalo)
    {
        vec4 SunPosProj = VPB * vec4(SunPos + rotate(Camera.X, Angle, Camera.Z) * SunR, 1.0f);
        SunPosProj /= SunPosProj.w;

        CalculateSunRaysLensFlareHalo |= (SunPosProj.x >= 0.0f && SunPosProj.x <= 1.0f && SunPosProj.y >= 0.0f && SunPosProj.y <= 1.0f && SunPosProj.z >= 0.0f && SunPosProj.z <= 1.0f);

        Angle += AngleInc;
        Test++;
    }

    if(CalculateSunRaysLensFlareHalo)
    {
        vec4 SunPosProj = VPB * vec4(SunPos, 1.0f);
        SunPosProj /= SunPosProj.w;

        glViewport(0, 0, SunTextureWidth, SunTextureHeight);

        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, SunTextures[1], 0);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, SunTextures[4], 0);

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glMatrixMode(GL_MODELVIEW);
        glLoadMatrixf(&ViewMatrix);
        glTranslatef(SunPos.x, SunPos.y, SunPos.z);
        glColor3f(1.0f, 0.90f, 0.80f);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);
        GLUquadric *obj = gluNewQuadric();
        gluSphere(obj, SunR, 16, 16);
        gluDeleteQuadric(obj);
        glDisable(GL_CULL_FACE);
        glDisable(GL_DEPTH_TEST);

        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, SunTextures[0], 0);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);

        glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, SunTextures[1]);
        glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, SunTextures[4]);
        glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, DepthTexture);
        glUseProgram(SunDepthTest);
        glBegin(GL_QUADS);
            glVertex2f(0.0f, 0.0f);
            glVertex2f(1.0f, 0.0f);
            glVertex2f(1.0f, 1.0f);
            glVertex2f(0.0f, 1.0f);
        glEnd();
        glUseProgram(0);
        glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, 0);
        glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0);
        glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0);

        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, SunTextures[2], 0);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);

        glBindTexture(GL_TEXTURE_2D, SunTextures[0]);
        glUseProgram(BlurH);
        glUniform1i(glGetUniformLocation(BlurH, "Width"), 1);
        glBegin(GL_QUADS);
            glVertex2f(0.0f, 0.0f);
            glVertex2f(1.0f, 0.0f);
            glVertex2f(1.0f, 1.0f);
            glVertex2f(0.0f, 1.0f);
        glEnd();
        glUseProgram(0);
        glBindTexture(GL_TEXTURE_2D, 0);

        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, SunTextures[1], 0);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);

        glBindTexture(GL_TEXTURE_2D, SunTextures[2]);
        glUseProgram(BlurV);
        glUniform1i(glGetUniformLocation(BlurV, "Width"), 1);
        glBegin(GL_QUADS);
            glVertex2f(0.0f, 0.0f);
            glVertex2f(1.0f, 0.0f);
            glVertex2f(1.0f, 1.0f);
            glVertex2f(0.0f, 1.0f);
        glEnd();
        glUseProgram(0);
        glBindTexture(GL_TEXTURE_2D, 0);

        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, SunTextures[3], 0);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);

        glBindTexture(GL_TEXTURE_2D, SunTextures[0]);
        glUseProgram(BlurH);
        glUniform1i(glGetUniformLocation(BlurH, "Width"), 10);
        glBegin(GL_QUADS);
            glVertex2f(0.0f, 0.0f);
            glVertex2f(1.0f, 0.0f);
            glVertex2f(1.0f, 1.0f);
            glVertex2f(0.0f, 1.0f);
        glEnd();
        glUseProgram(0);
        glBindTexture(GL_TEXTURE_2D, 0);

        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, SunTextures[2], 0);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);

        glBindTexture(GL_TEXTURE_2D, SunTextures[3]);
        glUseProgram(BlurV);
        glUniform1i(glGetUniformLocation(BlurV, "Width"), 10);
        glBegin(GL_QUADS);
            glVertex2f(0.0f, 0.0f);
            glVertex2f(1.0f, 0.0f);
            glVertex2f(1.0f, 1.0f);
            glVertex2f(0.0f, 1.0f);
        glEnd();
        glUseProgram(0);
        glBindTexture(GL_TEXTURE_2D, 0);

        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, SunTextures[3], 0);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);

        glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, SunTextures[1]);
        glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, SunTextures[2]);
        glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, DirtTexture);
        glUseProgram(SunRaysLensFlareHalo);
        glUniform2fv(glGetUniformLocation(SunRaysLensFlareHalo, "SunPosProj"), 1, &SunPosProj);
        glBegin(GL_QUADS);
            glVertex2f(0.0f, 0.0f);
            glVertex2f(1.0f, 0.0f);
            glVertex2f(1.0f, 1.0f);
            glVertex2f(0.0f, 1.0f);
        glEnd();
        glUseProgram(0);
        glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, 0);
        glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0);
        glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0);

        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

        glViewport(0, 0, Width, Height);
    }

    glMatrixMode(GL_PROJECTION);
    glLoadMatrixf(&ortho(0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f));

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    /*glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, ScreenTexture);
    glColor3f(1.0f, 1.0f, 1.0f);
    glBegin(GL_QUADS);
        glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
        glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 0.0f);
        glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
        glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 1.0f);
    glEnd();
    glBindTexture(GL_TEXTURE_2D, 0);
    glDisable(GL_TEXTURE_2D);*/

    if(CalculateSunRaysLensFlareHalo)
    {
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, SunTextures[3]);
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
        glEnable(GL_BLEND);
        glColor3f(1.0f, 1.0f, 1.0f);
        glBegin(GL_QUADS);
            glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
            glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 0.0f);
            glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
            glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 1.0f);
        glEnd();
        glDisable(GL_BLEND);
        glBindTexture(GL_TEXTURE_2D, 0);
        glDisable(GL_TEXTURE_2D);
    }
}

void COpenGLRenderer::Resize(int Width, int Height)
{
    this->Width = Width;
    this->Height = Height;

    ProjectionMatrix = perspective(45.0f, (float)Width / (float)Height, 0.125f, 512.0f);

    /*glBindTexture(GL_TEXTURE_2D, ScreenTexture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glBindTexture(GL_TEXTURE_2D, 0);*/

    glBindTexture(GL_TEXTURE_2D, DepthTexture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, Width, Height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
    glBindTexture(GL_TEXTURE_2D, 0);

    SunTextureWidth = Width / 2;
    SunTextureHeight = Height / 2;

    for(int i = 0; i < 4; i++)
    {
        glBindTexture(GL_TEXTURE_2D, SunTextures[i]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, SunTextureWidth, SunTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
        glBindTexture(GL_TEXTURE_2D, 0);
    }

    glBindTexture(GL_TEXTURE_2D, SunTextures[4]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, SunTextureWidth, SunTextureHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
    glBindTexture(GL_TEXTURE_2D, 0);

    glUseProgram(BlurH);
    glUniform1f(glGetUniformLocation(BlurH, "odw"), 1.0f / (float)SunTextureWidth);
    glUseProgram(BlurV);
    glUniform1f(glGetUniformLocation(BlurV, "odh"), 1.0f / (float)SunTextureHeight);
    glUseProgram(0);
}

void COpenGLRenderer::Destroy()
{
    DirtTexture.Destroy();

    //glDeleteTextures(1, &ScreenTexture);
    glDeleteTextures(1, &DepthTexture);
    glDeleteTextures(5, SunTextures);

    SunDepthTest.Destroy();
    BlurH.Destroy();
    BlurV.Destroy();
    SunRaysLensFlareHalo.Destroy();

    if(GLEW_EXT_framebuffer_object)
    {
        glDeleteFramebuffersEXT(1, &FBO);
    }
}

...
sundepthtest.vs
#version 120

void main()
{
    gl_TexCoord[0] = gl_Vertex;
    gl_Position = gl_Vertex * 2.0 - 1.0;
}
sundepthtest.fs
#version 120

uniform sampler2D SunTexture, SunDepthTexture, DepthTexture;

void main()
{
    if(texture2D(DepthTexture, gl_TexCoord[0].st).r < texture2D(SunDepthTexture, gl_TexCoord[0].st).r)
    {
        gl_FragColor = vec4(vec3(0.0), 1.0);
    }
    else
    {
        gl_FragColor = vec4(texture2D(SunTexture, gl_TexCoord[0].st).rgb, 1.0);
    }
}
blur.vs
#version 120

void main(void)
{
    gl_TexCoord[0] = gl_Vertex;
    gl_Position = gl_Vertex * 2.0 - 1.0;
}
blurh.fs
#version 120

uniform sampler2D Texture;
uniform int Width;
uniform float odw;

void main()
{
    vec3 Color = vec3(0.0);
    int wp1 = Width + 1;
    float Sum = 0.0;
    
    for(int x = -Width; x <= Width; x++)
    {
        float width = (wp1 - abs(float(x)));
        Color += texture2D(Texture, gl_TexCoord[0].st + vec2(odw * x, 0.0)).rgb * width;
        Sum += width;
    }
    
    gl_FragColor = vec4(Color / Sum, 1.0);
}
blurv.fs
#version 120

uniform sampler2D Texture;
uniform int Width;
uniform float odh;

void main()
{
    vec3 Color = vec3(0.0);
    int wp1 = Width + 1;
    float Sum = 0.0;
    
    for(int y = -Width; y <= Width; y++)
    {
        float width = (wp1 - abs(float(y)));
        Color += texture2D(Texture, gl_TexCoord[0].st + vec2(0.0, odh * y)).rgb * width;
        Sum += width;
    }
    
    gl_FragColor = vec4(Color / Sum, 1.0);
}
sunrayslensflarehalo.vs
#version 120

void main(void)
{
    gl_TexCoord[0] = gl_Vertex;
    gl_Position = gl_Vertex * 2.0 - 1.0;
}
sunrayslensflarehalo.fs
#version 120

uniform sampler2D LowBlurredSunTexture, HighBlurredSunTexture, DirtTexture;

uniform float Dispersal, HaloWidth, Intensity;
uniform vec2 SunPosProj;
uniform vec3 Distortion;

vec3 texture2DDistorted(sampler2D Texture, vec2 TexCoord, vec2 Offset)
{
    return vec3(
        texture2D(Texture, TexCoord + Offset * Distortion.r).r,
        texture2D(Texture, TexCoord + Offset * Distortion.g).g,
        texture2D(Texture, TexCoord + Offset * Distortion.b).b
    );
}

void main()
{
    vec3 RadialBlur = vec3(0.0);
    vec2 TexCoord = gl_TexCoord[0].st;
    int RadialBlurSamples = 128;
    vec2 RadialBlurVector = (SunPosProj - TexCoord) / RadialBlurSamples;

    for(int i = 0; i < RadialBlurSamples; i++)
    {
        RadialBlur += texture2D(LowBlurredSunTexture, TexCoord).rgb;
        TexCoord += RadialBlurVector;
    }

    RadialBlur /= RadialBlurSamples;

    vec3 LensFlareHalo = vec3(0.0);
    TexCoord = 1.0 - gl_TexCoord[0].st;
    vec2 LensFlareVector = (vec2(0.5) - TexCoord) * Dispersal;
    vec2 LensFlareOffset = vec2(0.0);

    for(int i = 0; i < 5; i++)
    {
        LensFlareHalo += texture2DDistorted(HighBlurredSunTexture, TexCoord, LensFlareOffset).rgb;
        LensFlareOffset += LensFlareVector;
    }

    LensFlareHalo += texture2DDistorted(HighBlurredSunTexture, TexCoord, normalize(LensFlareVector) * HaloWidth);

    LensFlareHalo /= 6.0;

    gl_FragColor = vec4((texture2D(HighBlurredSunTexture, gl_TexCoord[0].st).rgb + (RadialBlur + LensFlareHalo) * texture2D(DirtTexture, gl_TexCoord[0].st).rgb) * Intensity, 1.0);
}
Download
sun_rays_lens_flare_halo.zip (Visual Studio 2005 Professional)

© 2010 - 2016 Bc. Michal Belanec, michalbelanec (at) centrum (dot) sk
Last update June 25, 2016
OpenGL® is a registered trademark of Silicon Graphics Inc.