Exemplo n.º 1
0
GLUSvoid GLUSAPIENTRY glusVector3Refractf(GLUSfloat result[3], const GLUSfloat incident[3], const GLUSfloat normal[3], const float eta)
{
	// see http://www.opengl.org/sdk/docs/manglsl/xhtml/refract.xml
	// see http://en.wikipedia.org/wiki/Snell%27s_law
	// see http://www.hugi.scene.org/online/coding/hugi%2023%20-%20torefrac.htm for a and b vector.
	// In this implementation, the incident vector points into the interface. So the sings do change.

	GLUSfloat nDotI = glusVector3Dotf(normal, incident);

	GLUSfloat k = 1.0f - eta * eta * (1.0f - nDotI * nDotI);

	if (k < 0.0f)
	{
		result[0] = 0.0f;
		result[1] = 0.0f;
		result[2] = 0.0f;
	}
	else
	{
		GLUSfloat a[3];
		GLUSfloat b[3];

		glusVector3MultiplyScalarf(a, incident, eta);

		glusVector3MultiplyScalarf(b, normal, eta * nDotI + sqrtf(k));

		glusVector3SubtractVector3f(result, a, b);
	}
}
Exemplo n.º 2
0
Vector3 Vector3::operator *(float scalar) const
{
    Vector3 result;

    glusVector3MultiplyScalarf(result.v, v, scalar);

    return result;
}
Exemplo n.º 3
0
GLUSfloat GLUSAPIENTRY glusVector3Fresnelf(const GLUSfloat incident[3], const GLUSfloat normal[3], const GLUSfloat R0)
{
	// see http://en.wikipedia.org/wiki/Schlick%27s_approximation

	GLUSfloat negIncident[3];

	glusVector3MultiplyScalarf(negIncident, incident, -1.0f);

	return R0 + (1.0f - R0) * powf(1.0f - glusVector3Dotf(negIncident, normal), 5.0f);
}
Exemplo n.º 4
0
GLUSvoid GLUSAPIENTRY glusVector3Reflectf(GLUSfloat result[3], const GLUSfloat incident[3], const GLUSfloat normal[3])
{
	glusVector3MultiplyScalarf(result, normal, 2.0f * glusVector3Dotf(normal, incident));

	glusVector3SubtractVector3f(result, incident, result);
}
Exemplo n.º 5
0
Arquivo: main.c Projeto: AJ92/OpenGL
static GLvoid march(GLfloat pixelColor[4], const GLfloat rayPosition[4], const GLfloat rayDirection[3], const GLint depth)
{
	GLint i, k, m, o;

	Primitive* primitiveNear = 0;

	GLfloat marchPosition[4];
	GLfloat marchDirection[3];

	GLfloat hitPosition[4];
	GLfloat hitDirection[3];

	GLfloat eyeDirection[3];

	GLfloat t = 0.0f;

	//

	pixelColor[0] = 0.0f;
	pixelColor[1] = 0.0f;
	pixelColor[2] = 0.0f;
	pixelColor[3] = 1.0f;

	//

	for (i = 0; i < MAX_STEPS; i++)
	{
		GLfloat distance = INFINITY;
		GLfloat currentDistance;
		Primitive* closestPrimitive = 0;

		glusVector3MultiplyScalarf(marchDirection, rayDirection, t);
		glusPoint4AddVector3f(marchPosition, rayPosition, marchDirection);

		for (k = 0; k < NUM_SPHERES + NUM_BOXES; k++)
		{
			Primitive* currentPrimitive = &g_allPrimitives[k];

			currentDistance = currentPrimitive->distanceFunction(marchPosition, currentPrimitive);

			if (currentDistance < distance)
			{
				distance = currentDistance;

				closestPrimitive = currentPrimitive;
			}
		}

		if (distance < EPSILON)
		{
			GLfloat samplePoints[4 * 6];

			// Copy hit position ...
			glusPoint4Copyf(hitPosition, marchPosition);

			// ... and calculate normal by sampling around the hit position.
			for (k = 0; k < 6; k++)
			{
				samplePoints[k*4+0] = hitPosition[0];
				samplePoints[k*4+1] = hitPosition[1];
				samplePoints[k*4+2] = hitPosition[2];
				samplePoints[k*4+3] = hitPosition[3];

				samplePoints[k*4+k/2] += GAMMA * (k%2 == 0 ? 1.0f : -1.0f);
			}
			for (k = 0; k < 3; k++)
			{
				hitDirection[k] = closestPrimitive->distanceFunction(&samplePoints[k*2*4 + 0], closestPrimitive) - closestPrimitive->distanceFunction(&samplePoints[k*2*4 + 4], closestPrimitive);
			}

			glusVector3Normalizef(hitDirection);

			primitiveNear = closestPrimitive;

			break;
		}

		// If t is larger than a given distance, assume that there is the nothing.
		if (t > MAX_DISTANCE)
		{
			break;
		}

		t += distance;
	}

	//

	// No intersection, return background color / ambient light.
	if (!primitiveNear)
	{
		pixelColor[0] = 0.8f;
		pixelColor[1] = 0.8f;
		pixelColor[2] = 0.8f;

		return;
	}

	//

	glusVector3MultiplyScalarf(eyeDirection, rayDirection, -1.0f);

	// Diffuse and specular color
	for (i = 0; i < NUM_LIGHTS; i++)
	{
		PointLight* pointLight = &g_allLights[i];

		GLboolean obstacle = GL_FALSE;
		GLfloat lightDirection[3];
		GLfloat incidentLightDirection[3];

		glusPoint4SubtractPoint4f(lightDirection, pointLight->position, hitPosition);
		glusVector3Normalizef(lightDirection);
		glusVector3MultiplyScalarf(incidentLightDirection, lightDirection, -1.0f);

		// Check for obstacles between current hit point surface and point light.
		for (k = 0; k < NUM_SPHERES + NUM_BOXES; k++)
		{
			Primitive* obstaclePrimitive = &g_allPrimitives[k];

			if (obstaclePrimitive == primitiveNear)
			{
				continue;
			}

			t = 0.0f;

			for (m = 0; m < MAX_STEPS; m++)
			{
				GLfloat distance = INFINITY;
				GLfloat currentDistance;
				Primitive* closestPrimitive = 0;

				glusVector3MultiplyScalarf(marchDirection, lightDirection, -t);
				glusPoint4AddVector3f(marchPosition, pointLight->position, marchDirection);

				for (o = 0; o < NUM_SPHERES + NUM_BOXES; o++)
				{
					Primitive* currentPrimitive = &g_allPrimitives[o];

					currentDistance = currentPrimitive->distanceFunction(marchPosition, currentPrimitive);

					if (currentDistance < distance && currentDistance >= 0.0f)
					{
						distance = currentDistance;

						closestPrimitive = currentPrimitive;
					}
					else if (currentDistance > distance && currentDistance < 0.0f)
					{
						distance = currentDistance;

						closestPrimitive = currentPrimitive;
					}
				}

				if (distance < EPSILON)
				{
					if (closestPrimitive != primitiveNear)
					{
						obstacle = GL_TRUE;
					}

					break;
				}

				if (t > MAX_DISTANCE)
				{
					break;
				}

				t += distance;
			}
		}

		// If no obstacle, illuminate hit point surface.
		if (!obstacle)
		{
			GLfloat diffuseIntensity = glusMathMaxf(0.0f, glusVector3Dotf(hitDirection, lightDirection));

			if (diffuseIntensity > 0.0f)
			{
				GLfloat specularReflection[3];

				GLfloat eDotR;

				pixelColor[0] = pixelColor[0] + diffuseIntensity * primitiveNear->material.diffuseColor[0] * pointLight->color[0];
				pixelColor[1] = pixelColor[1] + diffuseIntensity * primitiveNear->material.diffuseColor[1] * pointLight->color[1];
				pixelColor[2] = pixelColor[2] + diffuseIntensity * primitiveNear->material.diffuseColor[2] * pointLight->color[2];

				glusVector3Reflectf(specularReflection, incidentLightDirection, hitDirection);
				glusVector3Normalizef(specularReflection);

				eDotR = glusMathMaxf(0.0f, glusVector3Dotf(eyeDirection, specularReflection));

				if (eDotR > 0.0f)
				{
					GLfloat specularIntensity = powf(eDotR, primitiveNear->material.shininess);

					pixelColor[0] = pixelColor[0] + specularIntensity * primitiveNear->material.specularColor[0] * pointLight->color[0];
					pixelColor[1] = pixelColor[1] + specularIntensity * primitiveNear->material.specularColor[1] * pointLight->color[1];
					pixelColor[2] = pixelColor[2] + specularIntensity * primitiveNear->material.specularColor[2] * pointLight->color[2];
				}
			}
		}
	}

	// Emissive color
	pixelColor[0] = pixelColor[0] + primitiveNear->material.emissiveColor[0];
	pixelColor[1] = pixelColor[1] + primitiveNear->material.emissiveColor[1];
	pixelColor[2] = pixelColor[2] + primitiveNear->material.emissiveColor[2];
}
Exemplo n.º 6
0
Arquivo: main.c Projeto: Adon-m/OpenGL
static GLvoid trace(GLfloat pixelColor[4], const GLfloat rayPosition[4], const GLfloat rayDirection[3], const GLint depth)
{
	const GLfloat bias = 1e-4f;

	GLint i, k;

	GLfloat tNear = INFINITY;
	Sphere* sphereNear = 0;
	GLboolean insideSphereNear = GL_FALSE;

	GLfloat ray[3];

	GLfloat hitPosition[4];
	GLfloat hitDirection[3];

	GLfloat biasedPositiveHitPosition[4];
	GLfloat biasedNegativeHitPosition[4];
	GLfloat biasedHitDirection[3];

	GLfloat eyeDirection[3];

	//

	pixelColor[0] = 0.0f;
	pixelColor[1] = 0.0f;
	pixelColor[2] = 0.0f;
	pixelColor[3] = 1.0f;

	//

	for (i = 0; i < NUM_SPHERES; i++)
	{
		GLfloat t0 = INFINITY;
		GLfloat t1 = INFINITY;
		GLboolean insideSphere = GL_FALSE;

		Sphere* currentSphere = &g_allSpheres[i];

		GLint numberIntersections = glusIntersectRaySpheref(&t0, &t1, &insideSphere, rayPosition, rayDirection, currentSphere->center, currentSphere->radius);

		if (numberIntersections)
		{
			// If intersection happened inside the sphere, take second intersection point, as this one is on the surface.
			if (insideSphere)
			{
				t0 = t1;
			}

			// Found a sphere, which is closer.
			if (t0 < tNear)
			{
				tNear = t0;
				sphereNear = currentSphere;
				insideSphereNear = insideSphere;
			}
		}
	}

	//

	// No intersection, return background color / ambient light.
	if (!sphereNear)
	{
		pixelColor[0] = 0.8f;
		pixelColor[1] = 0.8f;
		pixelColor[2] = 0.8f;

		return;
	}

	// Calculate ray hit position ...
	glusVector3MultiplyScalarf(ray, rayDirection, tNear);
	glusPoint4AddVector3f(hitPosition, rayPosition, ray);

	// ... and normal
	glusPoint4SubtractPoint4f(hitDirection, hitPosition, sphereNear->center);
	glusVector3Normalizef(hitDirection);

	// If inside the sphere, reverse hit vector, as ray comes from inside.
	if (insideSphereNear)
	{
		glusVector3MultiplyScalarf(hitDirection, hitDirection, -1.0f);
	}

	//

	// Biasing, to avoid artifacts.
	glusVector3MultiplyScalarf(biasedHitDirection, hitDirection, bias);
	glusPoint4AddVector3f(biasedPositiveHitPosition, hitPosition, biasedHitDirection);
	glusPoint4SubtractVector3f(biasedNegativeHitPosition, hitPosition, biasedHitDirection);

	//

	GLfloat reflectionColor[4] = {0.0f, 0.0f, 0.0f, 1.0f};
	GLfloat refractionColor[4] = {0.0f, 0.0f, 0.0f, 1.0f};

	GLfloat fresnel = glusVector3Fresnelf(rayDirection, hitDirection, R0);

	// Reflection ...
	if (sphereNear->material.reflectivity > 0.0f && depth < MAX_RAY_DEPTH)
	{
		GLfloat reflectionDirection[3];

		glusVector3Reflectf(reflectionDirection, rayDirection, hitDirection);
		glusVector3Normalizef(reflectionDirection);

		trace(reflectionColor, biasedPositiveHitPosition, reflectionDirection, depth + 1);
	}

	// ... refraction.
	if (sphereNear->material.alpha < 1.0f && depth < MAX_RAY_DEPTH)
	{
		GLfloat refractionDirection[3];

		// If inside, it is from glass to air.
		GLfloat eta = insideSphereNear ? 1.0f / Eta : Eta;

		glusVector3Refractf(refractionDirection, rayDirection, hitDirection, eta);
		glusVector3Normalizef(refractionDirection);

		trace(refractionColor, biasedNegativeHitPosition, refractionDirection, depth + 1);
	}
	else
	{
		fresnel = 1.0f;
	}

	//

	glusVector3MultiplyScalarf(eyeDirection, rayDirection, -1.0f);

	// Diffuse and specular color
	for (i = 0; i < NUM_LIGHTS; i++)
	{
		PointLight* pointLight = &g_allLights[i];

		GLboolean obstacle = GL_FALSE;
		GLfloat lightDirection[3];
		GLfloat incidentLightDirection[3];

		glusPoint4SubtractPoint4f(lightDirection, pointLight->position, hitPosition);
		glusVector3Normalizef(lightDirection);
		glusVector3MultiplyScalarf(incidentLightDirection, lightDirection, -1.0f);

		// Check for obstacles between current hit point surface and point light.
		for (k = 0; k < NUM_SPHERES; k++)
		{
			Sphere* obstacleSphere = &g_allSpheres[k];

			if (obstacleSphere == sphereNear)
			{
				continue;
			}

			if (glusIntersectRaySpheref(0, 0, 0, biasedPositiveHitPosition, lightDirection, obstacleSphere->center, obstacleSphere->radius))
			{
				obstacle = GL_TRUE;

				break;
			}
		}

		// If no obstacle, illuminate hit point surface.
		if (!obstacle)
		{
			GLfloat diffuseIntensity = glusMaxf(0.0f, glusVector3Dotf(hitDirection, lightDirection));

			if (diffuseIntensity > 0.0f)
			{
				GLfloat specularReflection[3];

				GLfloat eDotR;

				pixelColor[0] = pixelColor[0] + diffuseIntensity * sphereNear->material.diffuseColor[0] * pointLight->color[0];
				pixelColor[1] = pixelColor[1] + diffuseIntensity * sphereNear->material.diffuseColor[1] * pointLight->color[1];
				pixelColor[2] = pixelColor[2] + diffuseIntensity * sphereNear->material.diffuseColor[2] * pointLight->color[2];

				glusVector3Reflectf(specularReflection, incidentLightDirection, hitDirection);
				glusVector3Normalizef(specularReflection);

				eDotR = glusMaxf(0.0f, glusVector3Dotf(eyeDirection, specularReflection));

				if (eDotR > 0.0f && !insideSphereNear)
				{
					GLfloat specularIntensity = powf(eDotR, sphereNear->material.shininess);

					pixelColor[0] = pixelColor[0] + specularIntensity * sphereNear->material.specularColor[0] * pointLight->color[0];
					pixelColor[1] = pixelColor[1] + specularIntensity * sphereNear->material.specularColor[1] * pointLight->color[1];
					pixelColor[2] = pixelColor[2] + specularIntensity * sphereNear->material.specularColor[2] * pointLight->color[2];
				}
			}
		}
	}

	// Emissive color
	pixelColor[0] = pixelColor[0] + sphereNear->material.emissiveColor[0];
	pixelColor[1] = pixelColor[1] + sphereNear->material.emissiveColor[1];
	pixelColor[2] = pixelColor[2] + sphereNear->material.emissiveColor[2];

	// Final color with reflection and refraction
	pixelColor[0] = (1.0f - fresnel) * refractionColor[0] * (1.0f - sphereNear->material.alpha) + pixelColor[0] * (1.0f - sphereNear->material.reflectivity) * sphereNear->material.alpha + fresnel * reflectionColor[0] * sphereNear->material.reflectivity;
	pixelColor[1] = (1.0f - fresnel) * refractionColor[1] * (1.0f - sphereNear->material.alpha) + pixelColor[1] * (1.0f - sphereNear->material.reflectivity) * sphereNear->material.alpha + fresnel * reflectionColor[1] * sphereNear->material.reflectivity;
	pixelColor[2] = (1.0f - fresnel) * refractionColor[2] * (1.0f - sphereNear->material.alpha) + pixelColor[2] * (1.0f - sphereNear->material.reflectivity) * sphereNear->material.alpha + fresnel * reflectionColor[2] * sphereNear->material.reflectivity;
}
Exemplo n.º 7
0
Arquivo: main.c Projeto: Adon-m/OpenGL
GLUSboolean init(GLUSvoid)
{
	GLUStextfile vertexSource;
	GLUStextfile fragmentSource;

	GLUStgaimage image;

	GLUSshape plane;

	GLint i;

	//

	glusLookAtf(g_viewMatrix, g_camera.eye[0], g_camera.eye[1], g_camera.eye[2], g_camera.center[0], g_camera.center[1], g_camera.center[2], g_camera.up[0], g_camera.up[1], g_camera.up[2]);

	//

	if (!initWavefront(g_viewMatrix, &g_light))
	{
		return GLUS_FALSE;
	}

	//

	glusLoadTextFile("../Example28/shader/texture.vert.glsl", &vertexSource);
	glusLoadTextFile("../Example28/shader/texture.frag.glsl", &fragmentSource);

	glusBuildProgramFromSource(&g_program, (const GLUSchar**)&vertexSource.text, 0, 0, 0, (const GLUSchar**)&fragmentSource.text);

	glusDestroyTextFile(&vertexSource);
	glusDestroyTextFile(&fragmentSource);

	//

	// Retrieve the uniform locations in the program.
	g_viewProjectionMatrixLocation = glGetUniformLocation(g_program.program, "u_viewProjectionMatrix");
	g_modelMatrixLocation = glGetUniformLocation(g_program.program, "u_modelMatrix");
	g_normalMatrixLocation = glGetUniformLocation(g_program.program, "u_normalMatrix");
	g_lightDirectionLocation = glGetUniformLocation(g_program.program, "u_lightDirection");
	g_repeatLocation = glGetUniformLocation(g_program.program, "u_repeat");
	g_textureLocation = glGetUniformLocation(g_program.program, "u_texture");

	// Retrieve the attribute locations in the program.
	g_vertexLocation = glGetAttribLocation(g_program.program, "a_vertex");
	g_normalLocation = glGetAttribLocation(g_program.program, "a_normal");
	g_texCoordLocation = glGetAttribLocation(g_program.program, "a_texCoord");

	//
	// SSAO shader etc.
	//

	glusLoadTextFile("../Example28/shader/ssao.vert.glsl", &vertexSource);
	glusLoadTextFile("../Example28/shader/ssao.frag.glsl", &fragmentSource);

	glusBuildProgramFromSource(&g_ssaoProgram, (const GLUSchar**)&vertexSource.text, 0, 0, 0, (const GLUSchar**)&fragmentSource.text);

	glusDestroyTextFile(&vertexSource);
	glusDestroyTextFile(&fragmentSource);

	//

	// Retrieve the uniform locations in the program.
	g_ssaoTextureLocation = glGetUniformLocation(g_ssaoProgram.program, "u_texture");
	g_ssaoNormalTextureLocation = glGetUniformLocation(g_ssaoProgram.program, "u_normalTexture");
	g_ssaoDepthTextureLocation = glGetUniformLocation(g_ssaoProgram.program, "u_depthTexture");
	g_ssaoKernelLocation = glGetUniformLocation(g_ssaoProgram.program, "u_kernel");
	g_ssaoRotationNoiseTextureLocation = glGetUniformLocation(g_ssaoProgram.program, "u_rotationNoiseTexture");
	g_ssaoRotationNoiseScaleLocation = glGetUniformLocation(g_ssaoProgram.program, "u_rotationNoiseScale");
	g_ssaoInverseProjectionMatrixLocation = glGetUniformLocation(g_ssaoProgram.program, "u_inverseProjectionMatrix");
	g_ssaoProjectionMatrixLocation = glGetUniformLocation(g_ssaoProgram.program, "u_projectionMatrix");
	g_ssaoRadiusLocation = glGetUniformLocation(g_ssaoProgram.program, "u_radius");

	// Retrieve the attribute locations in the program.
	g_ssaoVertexLocation = glGetAttribLocation(g_ssaoProgram.program, "a_vertex");
	g_ssaoTexCoordLocation = glGetAttribLocation(g_ssaoProgram.program, "a_texCoord");

	//
	// Blur shader etc.
	//

	glusLoadTextFile("../Example28/shader/blur.vert.glsl", &vertexSource);
	glusLoadTextFile("../Example28/shader/blur.frag.glsl", &fragmentSource);

	glusBuildProgramFromSource(&g_blurProgram, (const GLUSchar**)&vertexSource.text, 0, 0, 0, (const GLUSchar**)&fragmentSource.text);

	glusDestroyTextFile(&vertexSource);
	glusDestroyTextFile(&fragmentSource);

	//

	// Retrieve the uniform locations in the program.
	g_blurColorTextureLocation = glGetUniformLocation(g_blurProgram.program, "u_colorTexture");

	g_blurSSAOTextureLocation = glGetUniformLocation(g_blurProgram.program, "u_ssaoTexture");

	g_blurTexelStepLocation = glGetUniformLocation(g_blurProgram.program, "u_texelStep");

	g_blurNoSSAOLocation = glGetUniformLocation(g_blurProgram.program, "u_noSSAO");

	// Retrieve the attribute locations in the program.
	g_blurVertexLocation = glGetAttribLocation(g_blurProgram.program, "a_vertex");
	g_blurTexCoordLocation = glGetAttribLocation(g_blurProgram.program, "a_texCoord");

	//
	// Texture set up for the ground plane.
	//

	glusLoadTgaImage("wood_texture.tga", &image);

	glGenTextures(1, &g_texture);
	glBindTexture(GL_TEXTURE_2D, g_texture);

	glTexImage2D(GL_TEXTURE_2D, 0, image.format, image.width, image.height, 0, image.format, GL_UNSIGNED_BYTE, image.data);

	// Mipmap generation is now included in OpenGL 3 and above
	glGenerateMipmap(GL_TEXTURE_2D);

	// Trilinear filtering
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	glBindTexture(GL_TEXTURE_2D, 0);

	//
	// Setting up the SSAO frame buffer.
	//

	glGenTextures(1, &g_ssaoTexture);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, g_ssaoTexture);

	glTexImage2D(GL_TEXTURE_2D, 0, GLUS_RGB, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GLUS_RGB, GL_UNSIGNED_BYTE, 0);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);

	glBindTexture(GL_TEXTURE_2D, 0);

	//

	glGenTextures(1, &g_ssaoNormalTexture);
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, g_ssaoNormalTexture);

	glTexImage2D(GL_TEXTURE_2D, 0, GLUS_RGB, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GLUS_RGB, GL_UNSIGNED_BYTE, 0);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);

	glBindTexture(GL_TEXTURE_2D, 0);

	//

	glGenTextures(1, &g_ssaoDepthTexture);
	glActiveTexture(GL_TEXTURE2);
	glBindTexture(GL_TEXTURE_2D, g_ssaoDepthTexture);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);

	glBindTexture(GL_TEXTURE_2D, 0);

	//

	glGenFramebuffers(1, &g_ssaoFBO);
	glBindFramebuffer(GL_FRAMEBUFFER, g_ssaoFBO);

	// Attach the color buffer ...
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, g_ssaoTexture, 0);

	// Attach the normal buffer ...
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, g_ssaoNormalTexture, 0);

	// ... and the depth buffer,
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, g_ssaoDepthTexture, 0);

	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
	{
		printf("GL_FRAMEBUFFER_COMPLETE error 0x%x", glCheckFramebufferStatus(GL_FRAMEBUFFER));

		return GLUS_FALSE;
	}

	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	//
	// Setting up the blur frame buffer
	//

	glGenTextures(1, &g_blurTexture);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, g_blurTexture);

	glTexImage2D(GL_TEXTURE_2D, 0, GLUS_RGB, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GLUS_RGB, GL_UNSIGNED_BYTE, 0);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);

	glBindTexture(GL_TEXTURE_2D, 0);

	//

	glGenFramebuffers(1, &g_blurFBO);
	glBindFramebuffer(GL_FRAMEBUFFER, g_blurFBO);

	// Attach the color buffer ...
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, g_blurTexture, 0);

	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
	{
		printf("GL_FRAMEBUFFER_COMPLETE error 0x%x", glCheckFramebufferStatus(GL_FRAMEBUFFER));

		return GLUS_FALSE;
	}

	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	//
	// Ground plane setup.
	//

	glusCreatePlanef(&plane, 20.0f);

	g_numberIndicesPlane = plane.numberIndices;

	glGenBuffers(1, &g_verticesVBO);
	glBindBuffer(GL_ARRAY_BUFFER, g_verticesVBO);
	glBufferData(GL_ARRAY_BUFFER, plane.numberVertices * 4 * sizeof(GLfloat), (GLfloat*)plane.vertices, GL_STATIC_DRAW);

	glGenBuffers(1, &g_normalsVBO);
	glBindBuffer(GL_ARRAY_BUFFER, g_normalsVBO);
	glBufferData(GL_ARRAY_BUFFER, plane.numberVertices * 3 * sizeof(GLfloat), (GLfloat*)plane.normals, GL_STATIC_DRAW);

	glGenBuffers(1, &g_texCoordsVBO);
	glBindBuffer(GL_ARRAY_BUFFER, g_texCoordsVBO);
	glBufferData(GL_ARRAY_BUFFER, plane.numberVertices * 2 * sizeof(GLfloat), (GLfloat*)plane.texCoords, GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, 0);

	glGenBuffers(1, &g_indicesVBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indicesVBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, plane.numberIndices * sizeof(GLuint), (GLuint*)plane.indices, GL_STATIC_DRAW);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

	glusDestroyShapef(&plane);

	//

	glUseProgram(g_program.program);

	glGenVertexArrays(1, &g_vao);
	glBindVertexArray(g_vao);

	glBindBuffer(GL_ARRAY_BUFFER, g_verticesVBO);
	glVertexAttribPointer(g_vertexLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(g_vertexLocation);

	glBindBuffer(GL_ARRAY_BUFFER, g_normalsVBO);
	glVertexAttribPointer(g_normalLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(g_normalLocation);

	glBindBuffer(GL_ARRAY_BUFFER, g_texCoordsVBO);
	glVertexAttribPointer(g_texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(g_texCoordLocation);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indicesVBO);

	glBindVertexArray(0);

	//

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, g_texture);
	glUniform1i(g_textureLocation, 0);

	// How many times the surface texture is repeated.
	glUniform1f(g_repeatLocation, 6.0f);

	//
	// Post process plane setup.
	//

	glusCreatePlanef(&plane, 1.0f);

	g_numberIndicesPostprocessPlane = plane.numberIndices;

	glGenBuffers(1, &g_postprocessVerticesVBO);
	glBindBuffer(GL_ARRAY_BUFFER, g_postprocessVerticesVBO);
	glBufferData(GL_ARRAY_BUFFER, plane.numberVertices * 4 * sizeof(GLfloat), (GLfloat*)plane.vertices, GL_STATIC_DRAW);

	glGenBuffers(1, &g_postprocessTexCoordsVBO);
	glBindBuffer(GL_ARRAY_BUFFER, g_postprocessTexCoordsVBO);
	glBufferData(GL_ARRAY_BUFFER, plane.numberVertices * 2 * sizeof(GLfloat), (GLfloat*)plane.texCoords, GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, 0);

	glGenBuffers(1, &g_postprocessIndicesVBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_postprocessIndicesVBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, plane.numberIndices * sizeof(GLuint), (GLuint*)plane.indices, GL_STATIC_DRAW);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

	glusDestroyShapef(&plane);

	//

	glUseProgram(g_ssaoProgram.program);

	glGenVertexArrays(1, &g_ssaoVAO);
	glBindVertexArray(g_ssaoVAO);

	glBindBuffer(GL_ARRAY_BUFFER, g_postprocessVerticesVBO);
	glVertexAttribPointer(g_ssaoVertexLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(g_ssaoVertexLocation);

	glBindBuffer(GL_ARRAY_BUFFER, g_postprocessTexCoordsVBO);
	glVertexAttribPointer(g_ssaoTexCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(g_ssaoTexCoordLocation);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_postprocessIndicesVBO);

	glBindVertexArray(0);

	//

	glUniform1i(g_ssaoTextureLocation, 0);
	glUniform1i(g_ssaoNormalTextureLocation, 1);
	glUniform1i(g_ssaoDepthTextureLocation, 2);
	glUniform1i(g_ssaoRotationNoiseTextureLocation, 3);

	glUniform1f(g_ssaoRadiusLocation, SSAO_RADIUS);

	//
	// Create the Kernel for SSAO.
	//

	for (i = 0; i < KERNEL_SIZE; i++)
	{
		g_kernel[i * 3 + 0] = glusRandomUniformGetFloatf(-1.0f, 1.0f);
		g_kernel[i * 3 + 1] = glusRandomUniformGetFloatf(-1.0f, 1.0f);
		g_kernel[i * 3 + 2] = glusRandomUniformGetFloatf(0.0f, 1.0f);	// Kernel hemisphere points to positive Z-Axis.

		glusVector3Normalizef(&g_kernel[i * 3]);					// Normalize, so included in the hemisphere.

		GLfloat scale = (GLfloat)i / (GLfloat)KERNEL_SIZE;		// Create a scale value between [0;1[ .

		scale = glusClampf(scale * scale, 0.1f, 1.0f);			// Adjust scale, that there are more values closer to the center of the g_kernel.

		glusVector3MultiplyScalarf(&g_kernel[i * 3], &g_kernel[i * 3], scale);
	}

	// Pass g_kernel to shader
	glUniform3fv(g_ssaoKernelLocation, KERNEL_SIZE, g_kernel);

	//
	// Create the rotation noise texture
	//

	for (i = 0; i < ROTATION_NOISE_SIZE; i++)
	{
		g_rotationNoise[i * 3 + 0] = glusRandomUniformGetFloatf(-1.0f, 1.0f);
		g_rotationNoise[i * 3 + 1] = glusRandomUniformGetFloatf(-1.0f, 1.0f);
		g_rotationNoise[i * 3 + 2] = 0.0f;						// Rotate on x-y-plane, so z is zero.

		glusVector3Normalizef(&g_rotationNoise[i * 3]);			// Normalized rotation vector.
	}

	//

	glGenTextures(1, &g_ssaoRotationNoiseTexture);
	glBindTexture(GL_TEXTURE_2D, g_ssaoRotationNoiseTexture);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, ROTATION_NOISE_SIDE_LENGTH, ROTATION_NOISE_SIDE_LENGTH, 0, GL_RGB, GL_FLOAT, g_rotationNoise);

	// No filtering
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	glBindTexture(GL_TEXTURE_2D, 0);

	//
	//

	g_rotationNoiseScale[0] = (GLfloat)TEXTURE_WIDTH / (GLfloat)ROTATION_NOISE_SIDE_LENGTH;
	g_rotationNoiseScale[1] = (GLfloat)TEXTURE_HEIGHT / (GLfloat)ROTATION_NOISE_SIDE_LENGTH;

	// Pass the scale, as the rotation noise texture is repeated over the screen x / y times.
	glUniform2fv(g_ssaoRotationNoiseScaleLocation, 1, g_rotationNoiseScale);

	//
	//

	glUseProgram(g_blurProgram.program);

	glGenVertexArrays(1, &g_blurVAO);
	glBindVertexArray(g_blurVAO);

	glBindBuffer(GL_ARRAY_BUFFER, g_postprocessVerticesVBO);
	glVertexAttribPointer(g_blurVertexLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(g_blurVertexLocation);

	glBindBuffer(GL_ARRAY_BUFFER, g_postprocessTexCoordsVBO);
	glVertexAttribPointer(g_blurTexCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(g_blurTexCoordLocation);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_postprocessIndicesVBO);

	glBindVertexArray(0);

	//

	glUniform1i(g_blurColorTextureLocation, 0);

	glUniform1i(g_blurSSAOTextureLocation, 1);

	g_texelStep[0] = 1.0f / (GLfloat)TEXTURE_WIDTH;
	g_texelStep[1] = 1.0f / (GLfloat)TEXTURE_HEIGHT;

	// Pass the value to step from one to another texel.
	glUniform2fv(g_blurTexelStepLocation, 1, g_texelStep);

	// Variable to toggle between SSAO on and off
	glUniform1f(g_blurNoSSAOLocation, 0.0f);

	//
	// Basic OpenGL set up.
	//

	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	glClearDepth(1.0f);

	glEnable(GL_DEPTH_TEST);

	return GLUS_TRUE;
}