コード例 #1
0
ファイル: main.c プロジェクト: 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];
}
コード例 #2
0
ファイル: main.c プロジェクト: 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;
}