示例#1
0
glm::vec4 ImageTexture::
evaluate_bilinear(int level, glm::vec2 const& uv) const
{
	cg_assert(level >= 0 && level < static_cast<int>(mip_levels.size()));
	cg_assert(mip_levels[level]);
	int const width = mip_levels[level]->getWidth();
	int const height = mip_levels[level]->getHeight();
	float fs = uv[0]*width+0.5f;
	float ft = uv[1]*height+0.5f;
	float const ffs = std::floor(fs);
	float const fft = std::floor(ft);
	float const ws = fs - ffs;
	float const wt = ft - fft;

	return (1.f-ws) * (1.f-wt) * get_texel(level, ffs-1, fft-1) + 
		   (1.f-ws) * (    wt) * get_texel(level, ffs-1, fft) + 
		   (    ws) * (1.f-wt) * get_texel(level, ffs,   fft-1) + 
		   (    ws) * (    wt) * get_texel(level, ffs,   fft); 
}
示例#2
0
glm::vec4 ImageTexture::
evaluate_nearest(int level, glm::vec2 const& uv) const
{
	cg_assert(level >= 0 && level < static_cast<int>(mip_levels.size()));
	cg_assert(mip_levels[level]);
	int const width = mip_levels[level]->getWidth();
	int const height = mip_levels[level]->getHeight();
	int const s = (int)std::floor(uv[0]*width);
	int const t = (int)std::floor(uv[1]*height);
	return get_texel(level, s, t);
}
示例#3
0
/*
 * Evaluates a texture for the given uv-coordinate without filtering.
 *
 * This method transformes the uv-coordinate into a st-coordinate and
 * rounds down to integer pixel values.
 *
 * The parameter level in [0, mip_levels.size()-1] is the miplevel of
 * the texture that is to be evaluated.
 */
glm::vec4 ImageTexture::
evaluate_nearest(int level, glm::vec2 const& uv) const
{
	cg_assert(level >= 0 && level < static_cast<int>(mip_levels.size()));
	cg_assert(mip_levels[level]);

	// TODO: compute the st-coordinates for the given uv-coordinates and mipmap level
	int s = floor(mip_levels[level]->getWidth() * uv[0]);
	int t = floor(mip_levels[level]->getHeight() * uv[1]);

	// get the value of pixel (s, t) of miplevel level
	return get_texel(level, s, t);
}
示例#4
0
Color4f TextureSource::sample_texture(
    TextureCache&               texture_cache,
    const Vector2d&             uv) const
{
    // Start with the transformed input texture coordinates.
    Vector2d p = apply_transform(uv);
    p.y = 1.0 - p.y;

    // Apply the texture addressing mode.
    apply_addressing_mode(m_texture_instance.get_addressing_mode(), p);

    switch (m_texture_instance.get_filtering_mode())
    {
      case TextureFilteringNearest:
        {
            p.x = clamp(p.x * m_scalar_canvas_width, 0.0, m_max_x);
            p.y = clamp(p.y * m_scalar_canvas_height, 0.0, m_max_y);

            const size_t ix = truncate<size_t>(p.x);
            const size_t iy = truncate<size_t>(p.y);

            return get_texel(texture_cache, ix, iy);
        }

      case TextureFilteringBilinear:
        {
            p.x *= m_max_x;
            p.y *= m_max_y;

            const int ix = truncate<int>(p.x);
            const int iy = truncate<int>(p.y);

            // Retrieve the four surrounding texels.
            Color4f t00, t10, t01, t11;
            get_texels_2x2(
                texture_cache,
                ix, iy,
                t00, t10, t01, t11);

            // Compute weights.
            const float wx1 = static_cast<float>(p.x - ix);
            const float wy1 = static_cast<float>(p.y - iy);
            const float wx0 = 1.0f - wx1;
            const float wy0 = 1.0f - wy1;

            // Apply weights.
            t00 *= wx0 * wy0;
            t10 *= wx1 * wy0;
            t01 *= wx0 * wy1;
            t11 *= wx1 * wy1;

            // Accumulate.
            t00 += t10;
            t00 += t01;
            t00 += t11;

            return t00;
        }

      default:
        assert(!"Wrong texture filtering mode.");
        return Color4f(0.0f);
    }
}
示例#5
0
glm::vec4 ImageTexture::
evaluate_bilinear(int level, glm::vec2 const& uv) const
{
	cg_assert(level >= 0 && level < static_cast<int>(mip_levels.size()));
	cg_assert(mip_levels[level]);

	const int width = mip_levels[level]->getWidth(), height = mip_levels[level]->getHeight();

	float intpart = 0.f;
	const glm::vec2 st{ uv[0] * width, uv[1] * height };

	//texel coordinates
	// (x1, y1)    (x2, y1)
	//
	// (x1, y2)    (x2, y2)



	//y coords of neighbouring texels, weight b
	float mod_t = std::modf(st[1], &intpart);
	mod_t += (mod_t < 0.f) ? 1.f : 0.f; //fractional part should be positive

	float w2 = mod_t; //weight b
	int y1 = floor(st[1]);
	int y2 = ceil(st[1]);

	if (y1 == y2) //mod_t == 0
	{
		--y1;
		w2 = 0.5f;
	}
	else if (mod_t < 0.5f)
	{
		--y1;
		--y2;
		w2 += 0.5f;
	}
    else if (mod_t == 0.5f)
    {
        --y1;
        --y2;
        w2 = 1.0f;
    }
	else //mod_t > 0.5f
		w2 -= 0.5f;
	
    //calculate x coords of neighbouring texels, weight a
	float mod_s = std::modf(st[0], &intpart);
	mod_s += (mod_s < 0.f) ? 1.f : 0.f; //fractional part should be positive

	float w1 = mod_s; //weight 1
	int x1 = floor(st[0]);
	int x2 = ceil(st[0]);
	
    if (x1 == x2) //mod_s == 0
	{
		--x1;
		w1 = 0.5f;
	}
	else if (mod_s < 0.5f)
	{
		--x1;
		--x2;
		w1 += 0.5f;
	}
    else if (mod_s == 0.5f)
    {
		--x1;
		--x2;
		w1 = 1.0f;
    }
	else //mod_s > 0.5f
		w1 -= 0.5f;


	// linear interpolations
	glm::vec4 t34 = (1.f - w1) * get_texel(level, x1, y2) + w1 * get_texel(level, x2, y2);
    glm::vec4 t12 = (1.f - w1) * get_texel(level, x1, y1) + w1 * get_texel(level, x2, y1);

	//linear interpolation vertically
	return (1.f - w2) * t12 + w2 * t34;
}
示例#6
0
static INLINE void
sp_get_samples_3d(const struct tgsi_sampler *tgsi_sampler,
                  const float s[QUAD_SIZE],
                  const float t[QUAD_SIZE],
                  const float p[QUAD_SIZE],
                  boolean computeLambda,
                  float lodbias,
                  float rgba[NUM_CHANNELS][QUAD_SIZE])
{
   const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler);
   const struct softpipe_context *sp = samp->sp;
   const uint unit = samp->unit;
   const struct pipe_texture *texture = sp->texture[unit];
   const struct pipe_sampler_state *sampler = sp->sampler[unit];
   /* get/map pipe_surfaces corresponding to 3D tex slices */
   unsigned level0, level1, j, imgFilter;
   int width, height, depth;
   float levelBlend;
   const uint face = 0;

   choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias,
                        &level0, &level1, &levelBlend, &imgFilter);

   assert(sampler->normalized_coords);

   width = texture->width[level0];
   height = texture->height[level0];
   depth = texture->depth[level0];

   assert(width > 0);
   assert(height > 0);
   assert(depth > 0);

   switch (imgFilter) {
   case PIPE_TEX_FILTER_NEAREST:
      {
         int x[4], y[4], z[4];
         nearest_texcoord_4(sampler->wrap_s, s, width, x);
         nearest_texcoord_4(sampler->wrap_t, t, height, y);
         nearest_texcoord_4(sampler->wrap_r, p, depth, z);
         for (j = 0; j < QUAD_SIZE; j++) {
            get_texel(tgsi_sampler, face, level0, x[j], y[j], z[j], rgba, j);
            if (level0 != level1) {
               /* get texels from second mipmap level and blend */
               float rgba2[4][4];
               unsigned c;
               x[j] /= 2;
               y[j] /= 2;
               z[j] /= 2;
               get_texel(tgsi_sampler, face, level1, x[j], y[j], z[j], rgba2, j);
               for (c = 0; c < NUM_CHANNELS; c++) {
                  rgba[c][j] = lerp(levelBlend, rgba2[c][j], rgba[c][j]);
               }
            }
         }
      }
      break;
   case PIPE_TEX_FILTER_LINEAR:
   case PIPE_TEX_FILTER_ANISO:
      {
         int x0[4], x1[4], y0[4], y1[4], z0[4], z1[4];
         float xw[4], yw[4], zw[4]; /* interpolation weights */
         linear_texcoord_4(sampler->wrap_s, s, width,  x0, x1, xw);
         linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw);
         linear_texcoord_4(sampler->wrap_r, p, depth,  z0, z1, zw);

         for (j = 0; j < QUAD_SIZE; j++) {
            int c;
            float tx0[4][4], tx1[4][4];
            get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z0[j], tx0, 0);
            get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z0[j], tx0, 1);
            get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z0[j], tx0, 2);
            get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z0[j], tx0, 3);
            get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z1[j], tx1, 0);
            get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z1[j], tx1, 1);
            get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z1[j], tx1, 2);
            get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z1[j], tx1, 3);

            /* interpolate R, G, B, A */
            for (c = 0; c < 4; c++) {
               rgba[c][j] = lerp_3d(xw[j], yw[j], zw[j],
                                    tx0[c][0], tx0[c][1],
                                    tx0[c][2], tx0[c][3],
                                    tx1[c][0], tx1[c][1],
                                    tx1[c][2], tx1[c][3]);
            }

            if (level0 != level1) {
               /* get texels from second mipmap level and blend */
               float rgba2[4][4];
               x0[j] /= 2;
               y0[j] /= 2;
               z0[j] /= 2;
               x1[j] /= 2;
               y1[j] /= 2;
               z1[j] /= 2;
               get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z0[j], tx0, 0);
               get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z0[j], tx0, 1);
               get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z0[j], tx0, 2);
               get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z0[j], tx0, 3);
               get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z1[j], tx1, 0);
               get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z1[j], tx1, 1);
               get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z1[j], tx1, 2);
               get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z1[j], tx1, 3);

               /* interpolate R, G, B, A */
               for (c = 0; c < 4; c++) {
                  rgba2[c][j] = lerp_3d(xw[j], yw[j], zw[j],
                                        tx0[c][0], tx0[c][1],
                                        tx0[c][2], tx0[c][3],
                                        tx1[c][0], tx1[c][1],
                                        tx1[c][2], tx1[c][3]);
               }

               /* blend mipmap levels */
               for (c = 0; c < NUM_CHANNELS; c++) {
                  rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]);
               }
            }
         }
      }
      break;
   default:
      assert(0);
   }
}
示例#7
0
/**
 * Common code for sampling 1D/2D/cube textures.
 * Could probably extend for 3D...
 */
static void
sp_get_samples_2d_common(const struct tgsi_sampler *tgsi_sampler,
                         const float s[QUAD_SIZE],
                         const float t[QUAD_SIZE],
                         const float p[QUAD_SIZE],
                         boolean computeLambda,
                         float lodbias,
                         float rgba[NUM_CHANNELS][QUAD_SIZE],
                         const unsigned faces[4])
{
   const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler);
   const struct softpipe_context *sp = samp->sp;
   const uint unit = samp->unit;
   const struct pipe_texture *texture = sp->texture[unit];
   const struct pipe_sampler_state *sampler = sp->sampler[unit];
   const uint compare_func = sampler->compare_func;
   unsigned level0, level1, j, imgFilter;
   int width, height;
   float levelBlend;

   choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias,
                        &level0, &level1, &levelBlend, &imgFilter);

   assert(sampler->normalized_coords);

   width = texture->width[level0];
   height = texture->height[level0];

   assert(width > 0);

   switch (imgFilter) {
   case PIPE_TEX_FILTER_NEAREST:
      {
         int x[4], y[4];
         nearest_texcoord_4(sampler->wrap_s, s, width, x);
         nearest_texcoord_4(sampler->wrap_t, t, height, y);

         for (j = 0; j < QUAD_SIZE; j++) {
            get_texel(tgsi_sampler, faces[j], level0, x[j], y[j], 0, rgba, j);
            if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
               shadow_compare(compare_func, rgba, p, j);
            }

            if (level0 != level1) {
               /* get texels from second mipmap level and blend */
               float rgba2[4][4];
               unsigned c;
               x[j] /= 2;
               y[j] /= 2;
               get_texel(tgsi_sampler, faces[j], level1, x[j], y[j], 0,
                         rgba2, j);
               if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){
                  shadow_compare(compare_func, rgba2, p, j);
               }

               for (c = 0; c < NUM_CHANNELS; c++) {
                  rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]);
               }
            }
         }
      }
      break;
   case PIPE_TEX_FILTER_LINEAR:
   case PIPE_TEX_FILTER_ANISO:
      {
         int x0[4], y0[4], x1[4], y1[4];
         float xw[4], yw[4]; /* weights */

         linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw);
         linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw);

         for (j = 0; j < QUAD_SIZE; j++) {
            float tx[4][4]; /* texels */
            int c;
            get_texel(tgsi_sampler, faces[j], level0, x0[j], y0[j], 0, tx, 0);
            get_texel(tgsi_sampler, faces[j], level0, x1[j], y0[j], 0, tx, 1);
            get_texel(tgsi_sampler, faces[j], level0, x0[j], y1[j], 0, tx, 2);
            get_texel(tgsi_sampler, faces[j], level0, x1[j], y1[j], 0, tx, 3);
            if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
               shadow_compare(compare_func, tx, p, 0);
               shadow_compare(compare_func, tx, p, 1);
               shadow_compare(compare_func, tx, p, 2);
               shadow_compare(compare_func, tx, p, 3);
            }

            /* interpolate R, G, B, A */
            for (c = 0; c < 4; c++) {
               rgba[c][j] = lerp_2d(xw[j], yw[j],
                                    tx[c][0], tx[c][1],
                                    tx[c][2], tx[c][3]);
            }

            if (level0 != level1) {
               /* get texels from second mipmap level and blend */
               float rgba2[4][4];
               x0[j] /= 2;
               y0[j] /= 2;
               x1[j] /= 2;
               y1[j] /= 2;
               get_texel(tgsi_sampler, faces[j], level1, x0[j], y0[j], 0, tx, 0);
               get_texel(tgsi_sampler, faces[j], level1, x1[j], y0[j], 0, tx, 1);
               get_texel(tgsi_sampler, faces[j], level1, x0[j], y1[j], 0, tx, 2);
               get_texel(tgsi_sampler, faces[j], level1, x1[j], y1[j], 0, tx, 3);
               if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){
                  shadow_compare(compare_func, tx, p, 0);
                  shadow_compare(compare_func, tx, p, 1);
                  shadow_compare(compare_func, tx, p, 2);
                  shadow_compare(compare_func, tx, p, 3);
               }

               /* interpolate R, G, B, A */
               for (c = 0; c < 4; c++) {
                  rgba2[c][j] = lerp_2d(xw[j], yw[j],
                                        tx[c][0], tx[c][1], tx[c][2], tx[c][3]);
               }

               for (c = 0; c < NUM_CHANNELS; c++) {
                  rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]);
               }
            }
         }
      }
      break;
   default:
      assert(0);
   }
}