3D C/C++ tutorials -> OpenGL 2.1 -> God rays
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.
opengl_21_tutorials_win32_framework.h
...
class COpenGLRenderer
{
protected:
...
protected:
CShaderProgram PerPixelLighting, GodRays;
GLuint VBO, VerticesCount, ColorBuffer, DepthBuffer, FBO;
public:
bool Blur, WireFrame;
public:
...
};
...
opengl_21_tutorials_win32_framework.cpp
...
COpenGLRenderer::COpenGLRenderer()
{
Blur = true;
WireFrame = false;
Camera.SetViewMatrixPointer(&ViewMatrix);
}
COpenGLRenderer::~COpenGLRenderer()
{
}
bool COpenGLRenderer::Init()
{
// ------------------------------------------------------------------------------------------------------------------------
bool Error = false;
// check OpenGL extensions ------------------------------------------------------------------------------------------------
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;
}
// load textures and shaders ----------------------------------------------------------------------------------------------
Error |= !PerPixelLighting.Load("per_pixel_lighting.vs", "per_pixel_lighting.fs");
Error |= !GodRays.Load("god_rays.vs", "god_rays.fs");
// if an error occurred, return false -------------------------------------------------------------------------------------
if(Error)
{
return false;
}
// init vertex arrays -----------------------------------------------------------------------------------------------------
CBuffer Buffer;
int twists = 5, ures = 64, vres = 32;
float radius = 5.0f, thickness = 5.0f, length = 45.0f;
float uinc = 360.0f / ures, vinc = 360.0f / vres, zinc = length / twists / ures;
vec3 z = vec3(0.0f, 0.0f, 1.0f);
vec3 a = vec3(radius, 0.0f, 0.0f), b = rotate(a, uinc, z), c = rotate(b, uinc, z);
vec3 x1 = vec3(thickness / 2.0f, 0.0f, 0.0f), x2 = rotate(x1, uinc, z);
float az = -length / 2.0f, bz = az + zinc, cz = bz + zinc;
vec3 Normal, Vertex;
for(float u = 0.0f; u < 360.0f * twists; u += 360.0f / ures)
{
vec3 m1 = vec3(a.x, a.y, az);
vec3 m2 = vec3(b.x, b.y, bz);
vec3 m3 = vec3(c.x, c.y, cz);
vec3 y1 = normalize(m2 - m1);
vec3 y2 = normalize(m3 - m2);
for(float v = 0.0f; v < 360.0f; v += 360.0f / vres)
{
vec3 x1a = x1, x1b = rotate(x1, vinc, y1), x2a = x2, x2b = rotate(x2, vinc, y2);
Normal = normalize(x1a); Buffer.AddData(&Normal, 12); Vertex = m1 + x1a; Buffer.AddData(&Vertex, 12);
Normal = normalize(x1b); Buffer.AddData(&Normal, 12); Vertex = m1 + x1b; Buffer.AddData(&Vertex, 12);
Normal = normalize(x2b); Buffer.AddData(&Normal, 12); Vertex = m2 + x2b; Buffer.AddData(&Vertex, 12);
Normal = normalize(x2a); Buffer.AddData(&Normal, 12); Vertex = m2 + x2a; Buffer.AddData(&Vertex, 12);
x1 = x1b; x2 = x2b;
}
x1 = rotate(x1, uinc, z);
x2 = rotate(x2, uinc, z);
a = b; az = bz;
b = c; bz = cz;
c = rotate(c, uinc, z); cz += zinc;
}
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, Buffer.GetDataSize(), Buffer.GetData(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
VerticesCount = Buffer.GetDataSize() / 24;
Buffer.Empty();
// generate textures ------------------------------------------------------------------------------------------------------
glGenTextures(1, &ColorBuffer);
glGenTextures(1, &DepthBuffer);
// generate FBO -----------------------------------------------------------------------------------------------------------
glGenFramebuffersEXT(1, &FBO);
// set camera -------------------------------------------------------------------------------------------------------------
Camera.Look(vec3(90.0f, 0.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f), true);
// ------------------------------------------------------------------------------------------------------------------------
return true;
}
void COpenGLRenderer::Render(float FrameTime)
{
// bind FBO ---------------------------------------------------------------------------------------------------------------
if(Blur)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, ColorBuffer, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, DepthBuffer, 0);
}
// render scene -----------------------------------------------------------------------------------------------------------
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(&ViewMatrix);
glEnable(GL_DEPTH_TEST);
if(WireFrame)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
glUseProgram(PerPixelLighting);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 24, (void*)0);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 24, (void*)12);
glColor3f(0.4f, 0.2f, 0.8f);
glDrawArrays(GL_QUADS, 0, VerticesCount);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
if(WireFrame)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
glDisable(GL_DEPTH_TEST);
// blur ColorBuffer texture -----------------------------------------------------------------------------------------------
if(Blur)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_2D, ColorBuffer);
glUseProgram(GodRays);
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);
}
}
void COpenGLRenderer::Resize(int Width, int Height)
{
this->Width = Width;
this->Height = Height;
glViewport(0, 0, Width, Height);
ProjectionMatrix = perspective(45.0f, (float)Width / (float)Height, 0.125f, 512.0f);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(&ProjectionMatrix);
glBindTexture(GL_TEXTURE_2D, ColorBuffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, DepthBuffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, Width, Height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
}
void COpenGLRenderer::Destroy()
{
PerPixelLighting.Destroy();
GodRays.Destroy();
glDeleteBuffers(1, &VBO);
glDeleteTextures(1, &ColorBuffer);
glDeleteTextures(1, &DepthBuffer);
if(GLEW_EXT_framebuffer_object)
{
glDeleteFramebuffersEXT(1, &FBO);
}
}
...
void COpenGLView::OnKeyDown(UINT Key)
{
switch(Key)
{
case VK_F1:
OpenGLRenderer.Blur = !OpenGLRenderer.Blur;
break;
case VK_F2:
OpenGLRenderer.WireFrame = !OpenGLRenderer.WireFrame;
break;
}
}
...
per_pixel_lighting.vs
#version 120
varying vec3 LD, Normal, LDR;
void main()
{
LD = -(gl_ModelViewMatrix * gl_Vertex).xyz;
Normal = gl_NormalMatrix * gl_Normal;
LDR = reflect(-LD, Normal);
gl_FrontColor = gl_Color;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
per_pixel_lighting.fs
#version 120
varying vec3 LD, Normal, LDR;
void main()
{
vec3 LDN = normalize(LD);
vec3 NormalN = normalize(Normal);
vec3 LDRN = normalize(LDR);
float NdotLD = max(dot(NormalN, LDN), 0.0);
float EVdotLDR = pow(max(dot(LDN, LDRN), 0.0), 32.0);
gl_FragColor = vec4(gl_Color.rgb * NdotLD + vec3(EVdotLDR), 1.0);
}
god_rays.vs
#version 120
void main()
{
gl_TexCoord[0] = gl_Vertex;
gl_Position = gl_Vertex * 2.0 - 1.0;
}
god_rays.fs
#version 120
uniform sampler2D ColorBuffer;
void main()
{
int Samples = 128;
float Intensity = 0.125, Decay = 0.96875;
vec2 TexCoord = gl_TexCoord[0].st, Direction = vec2(0.5) - TexCoord;
Direction /= Samples;
vec3 Color = texture2D(ColorBuffer, TexCoord).rgb;
for(int Sample = 0; Sample < Samples; Sample++)
{
Color += texture2D(ColorBuffer, TexCoord).rgb * Intensity;
Intensity *= Decay;
TexCoord += Direction;
}
gl_FragColor = vec4(Color, 1.0);
}
Download
|