Example #1
0
//////////////////////////////////////////////////////////////////////////////
// NAME:
// ARGUMENTS:
// RETURN:
// DESCRIPTION:
//
// NOTE:  This function should only be called from DxLight::Manager::Light()
//////////////////////////////////////////////////////////////////////////////
void DxLight::DirectLight(VertexL *dst, U32 count)
{
	ASSERT( dst );

	if (!IsActive())
	{
		return;
	}

	Material *material = Manager::curMaterial;
#if 0
	if ( count == 0 || (material_diffuse.r + material_diffuse.g + material_diffuse.b + material_diffuse.a) == 0.0f )
	{
		return;
	}
#endif

	// calculate the vector to the light in model space
#ifndef DOBZ2
	direction = WorldMatrix().Front();
#else
	direction = CalcSimWorldDirection(Vector(0, 0, 1));
#endif
  direction *= -1.0f;
	Vid::world_matrix.RotateInv(direction);

	Bool do_specular = (material->status.specular && Vid::renderState.status.specular && (desc.dwFlags & D3DLIGHT_NO_SPECULAR) != D3DLIGHT_NO_SPECULAR);

  if (do_specular)
  {
  	// calculate the halfway vector using the D3D method
	  halfVector = (Vid::model_view_norm + direction);
	  halfVector.Normalize();
  }

	VertexL *out = dst;
  ColorValue *d = &Manager::diffuse[0];
  ColorValue *s = &Manager::specular[0];
  U32 iv;
	for (iv = 0; iv < count; iv++ )
	{
		// calculate the diffuse reflection factor and clamp it to [0,1]
		// NOTE: both src->nv and light->dvDirection must be normalized vectors
		F32 diffuse_reflect = Manager::norms[iv].Dot(direction); // -1.0f <= diffuse_reflect <= 1.0f

		if (diffuse_reflect > 0.0f)
		{
			// calculate the diffuse component for the vertex
      d->r += desc.dcvColor.r * diffuse_reflect * Manager::material_diffuse.r;
      d->g += desc.dcvColor.g * diffuse_reflect * Manager::material_diffuse.g;
      d->b += desc.dcvColor.b * diffuse_reflect * Manager::material_diffuse.b;
		}

		if (do_specular)
		{
			// calculate the partial specular reflection factor
			F32 specular_reflect = Manager::norms[iv].Dot(halfVector);

			if ( spec_reflect > SPECULAR_THRESHOLD )
			{
#if 0
				spec_reflect = (F32) pow((double) spec_reflect, (double) material->GetDesc().dvPower); // -1.0f <= spec_reflect <= 1.0f
#else
        // apply the material's power factor to the nearest power of 2
        U32 e, ee = material->PowerCount();
        for (e = 1; e < ee; e *= 2 )
        {
          spec_reflect = spec_reflect * spec_reflect; 
        }
#endif
				// calculate the diffuse component of the vertex
				// if vertex color capabilities are added this must be changed
        s->r += desc.dcvColor.r * specular_reflect * Manager::material_specular.r;
        s->g += desc.dcvColor.g * specular_reflect * Manager::material_specular.g;
        s->b += desc.dcvColor.b * specular_reflect * Manager::material_specular.b;
			}
		}

		out++;
    d++;
    s++;

	} // for
}
Example #2
0
void DxLight::PointLight(Vertex *src, U32 count)
{
	ASSERT( src );

	if (!IsActive())
	{
		return;
	}

  Material *material = Manager::curMaterial;

	// calculate the light's model space position
	Matrix inverse_world_matrix;
	inverse_world_matrix.SetInverse(Vid::world_matrix);
#ifndef DOBZ2
	inverse_world_matrix.Transform(position, WorldMatrix().Position());
#else
	Vector Centre (CalcSimWorldPosition(Vector (0, 0, 0)));
	inverse_world_matrix.Transform(position, Centre);
#endif

	// calculate the model space direction
  direction = position;
  direction.Normalize();

	Bool do_specular = (material->status.specular && Vid::renderState.status.specular && (desc.dwFlags & D3DLIGHT_NO_SPECULAR) != D3DLIGHT_NO_SPECULAR);

  if (do_specular)
  {
  	// calculate the halfway vector using the D3D method
	  halfVector = (Vid::model_view_norm + direction);
  	halfVector.Normalize();
  }

	Vertex *in = src;
  ColorValue *d = &Manager::diffuse[0];
  ColorValue *s = &Manager::specular[0];
  U32 iv;
	for (iv = 0; iv < count; iv++ )
	{
		// calculate distance from the light to the vertex 
		direction = position - in->vv;
		F32 dist = direction.Magnitude();

		// if distance is greater than range, then no light reaches the vertex
    // this could use a Magnitude2() check to avoid the sqrt for verts outside range !!!
		if ( dist <= desc.dvRange )
		{
//      ASSERT( dist > 0.0f);
      if (dist <= F32_EPSILON)
      {
        dist = F32_EPSILON;
      }
      F32 invdist = 1.0f / dist; 

			// normalize the distance
			dist = (desc.dvRange - dist) * invRange;

			// calculate the attenuation over that distance
			F32 a = desc.dvAttenuation0 + dist * desc.dvAttenuation1 + (dist*dist) * desc.dvAttenuation2;

			if ( a > 0.0f )
			{
		    // calculate the model space direction
        direction.x *= invdist;
        direction.y *= invdist;
        direction.z *= invdist;

				// calculate and scale the attenuated color values
				ColorValue atten;
				atten.r = a * desc.dcvColor.r;
				atten.g = a * desc.dcvColor.g;
				atten.b = a * desc.dcvColor.b;

				// calculate the diffuse reflection factor and clamp it to [0,1]
				// NOTE: both src->nv and light->dvDirection must be normalized vectors
				F32 diffuse_reflect = in->nv.Dot(direction); // -1.0f <= diffuse_reflect <= 1.0f

				if ( diffuse_reflect > 0.0f )
				{
					// calculate the diffuse component for the vertex
          d->r += atten.r * diffuse_reflect * Manager::material_diffuse.r;
          d->g += atten.g * diffuse_reflect * Manager::material_diffuse.g;
          d->b += atten.b * diffuse_reflect * Manager::material_diffuse.b;
				}

				if ( do_specular )
				{
  				// calculate the partial specular reflection factor
					F32 spec_reflect = in->nv.Dot(halfVector);
					
  				if ( spec_reflect > SPECULAR_THRESHOLD )
					{
#if 0
  					spec_reflect = (F32) pow((double) spec_reflect, (double) material->GetDesc().dvPower); // -1.0f <= spec_reflect <= 1.0f
#else
            // apply the material's power factor to the nearest power of 2
            U32 e, ee = material->PowerCount();
            for (e = 1; e < ee; e *= 2 )
            {
              spec_reflect = spec_reflect * spec_reflect; 
            }
#endif

            // calculate the diffuse component of the vertex
						// if vertex color capabilities are added this must be changed
            s->r += atten.r * spec_reflect * Manager::material_specular.r;
            s->g += atten.g * spec_reflect * Manager::material_specular.g;
            s->b += atten.b * spec_reflect * Manager::material_specular.b;
					}
				}

			} // if

		} // if

		in++;
    d++;
    s++;

	} // for
}
Example #3
0
//////////////////////////////////////////////////////////////////////////////
// NAME:
// ARGUMENTS:
// RETURN:
// DESCRIPTION:
//
// NOTE:  This function should only be called from DxLight::Manager::Light()
//////////////////////////////////////////////////////////////////////////////
void DxLight::SpotLight(VertexL *dst, U32 count)
{
	ASSERT( dst );

	if (!IsActive())
	{
		return;
	}

	Material *material = Manager::curMaterial;
	// calculate the light's model space position
	Matrix inverse_world_matrix;
	inverse_world_matrix.SetInverse(Vid::world_matrix);
#ifndef DOBZ2
	inverse_world_matrix.Transform(position, WorldMatrix().Position());
#else
	Vector Centre (CalcSimWorldPosition(Vector (0, 0, 0)));
	inverse_world_matrix.Transform(position, Centre);
#endif

	// calculate the model space direction
  direction = position;
  direction.Normalize();

  // get the spot direction vector in model space
  Vector spot_direction;
#ifndef DOBZ2
	inverse_world_matrix.Rotate(spot_direction, WorldMatrix().Front());
#else
	Vector Dir (CalcSimWorldDirection(Vector (0, 0, 1)));
	inverse_world_matrix.Rotate(spot_direction, Dir);
#endif

	Bool do_specular = (material->status.specular && Vid::renderState.status.specular && (desc.dwFlags & D3DLIGHT_NO_SPECULAR) != D3DLIGHT_NO_SPECULAR);

  if (do_specular)
  {
    // calculate the halfway vector using the D3D method
	  halfVector = (Vid::model_view_norm + direction);
  	halfVector.Normalize();
  }

	VertexL *out = dst;	
  ColorValue *d = &Manager::diffuse[0];
  ColorValue *s = &Manager::specular[0];
  U32 iv;
	for (iv = 0; iv < count; iv++ )
	{
		// calculate distance from the light to the vertex 
		direction = position - out->vv;
		F32 dist = direction.Magnitude();

		// if distance is greater than range, then no light reaches the vertex
		if ( dist <= desc.dvRange )
		{
//      ASSERT( dist > 0.0f);
      if (dist <= F32_EPSILON)
      {
        dist = F32_EPSILON;
      }
      F32 invdist = 1.0f / dist;

			// normalize the distance
			dist = (desc.dvRange - dist) * invRange;

			// calculate the attenuation over that distance
			F32 a = desc.dvAttenuation0 + dist * desc.dvAttenuation1 + (dist*dist) * desc.dvAttenuation2;

			if ( a > 0.0f )
			{
				// compute the cosine of vectors vert_to_light and the light's model space direction
        direction *= invdist;
				F32 cos_dir = -direction.Dot(spot_direction);

				if ( cos_dir > cosPhi )
				{
					F32 intensity;

					if ( cos_dir > cosTheta ) // vertex is inside inner cone --> receives full light
					{
						intensity = 1.0f;	
					}
					else // vertex is between inner and outer cone
					{
//						intensity = (F32) pow((double) ((cos_dir-cos_phi)/(cos_theta-cos_phi)), (double) desc.dvFalloff);
						intensity = (cos_dir - cosPhi) * invAngle;
					}
				  // calculate and scale the attenuated color values
				  ColorValue atten;
				  atten.r = a * desc.dcvColor.r;
				  atten.g = a * desc.dcvColor.g;
				  atten.b = a * desc.dcvColor.b;
										
					// calculate the diffuse reflection factor and clamp it to [0,1]
					// NOTE: both src->nv and light->dvDirection must be normalized vectors
					F32 diffuse_reflect = Manager::norms[iv].Dot(direction); // -1.0f <= diffuse_reflect <= 1.0f

          if ( diffuse_reflect > 0.0f )
					{
						diffuse_reflect *= intensity;

						// calculate the diffuse component for the vertex
            d->r += atten.r * diffuse_reflect * Manager::material_diffuse.r;
            d->g += atten.g * diffuse_reflect * Manager::material_diffuse.g;
            d->b += atten.b * diffuse_reflect * Manager::material_diffuse.b;
					}

					if ( do_specular )
					{
						// calculate the partial specular reflection factor
						F32 spec_reflect = Manager::norms[iv].Dot(halfVector);
						
    				if ( spec_reflect > SPECULAR_THRESHOLD )
						{
#if 0
    					spec_reflect = (F32) pow((double) spec_reflect, (double) material->GetDesc().dvPower); // -1.0f <= spec_reflect <= 1.0f
#else
              // apply the material's power factor to the nearest power of 2
              U32 e, ee = material->PowerCount();
              for (e = 1; e < ee; e *= 2 )
              {
                spec_reflect = spec_reflect * spec_reflect; 
              }
#endif
							spec_reflect *= intensity;

              s->r += atten.r * spec_reflect * Manager::material_specular.r;
              s->g += atten.g * spec_reflect * Manager::material_specular.g;
              s->b += atten.b * spec_reflect * Manager::material_specular.b;
						}
					}

				} // if

			} // if

		} // if

		out++;
    d++;
    s++;

	} // for
}