📄 s_texfilter.c
字号:
const GLfloat texcoords[][4], const GLfloat lambda[], GLchan rgba[][4] ){ GLuint i; struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; (void) lambda; for (i=0;i<n;i++) { sample_3d_linear(ctx, tObj, image, texcoords[i], rgba[i]); }}/* * Given an (s,t,r) texture coordinate and lambda (level of detail) value, * return a texture sample. */static voidsample_lambda_3d( GLcontext *ctx, const struct gl_texture_object *tObj, GLuint n, const GLfloat texcoords[][4], const GLfloat lambda[], GLchan rgba[][4] ){ GLuint minStart, minEnd; /* texels with minification */ GLuint magStart, magEnd; /* texels with magnification */ GLuint i; ASSERT(lambda != NULL); compute_min_mag_ranges(tObj, n, lambda, &minStart, &minEnd, &magStart, &magEnd); if (minStart < minEnd) { /* do the minified texels */ GLuint m = minEnd - minStart; switch (tObj->MinFilter) { case GL_NEAREST: for (i = minStart; i < minEnd; i++) sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], texcoords[i], rgba[i]); break; case GL_LINEAR: for (i = minStart; i < minEnd; i++) sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], texcoords[i], rgba[i]); break; case GL_NEAREST_MIPMAP_NEAREST: sample_3d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart, lambda + minStart, rgba + minStart); break; case GL_LINEAR_MIPMAP_NEAREST: sample_3d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart, lambda + minStart, rgba + minStart); break; case GL_NEAREST_MIPMAP_LINEAR: sample_3d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, lambda + minStart, rgba + minStart); break; case GL_LINEAR_MIPMAP_LINEAR: sample_3d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart, lambda + minStart, rgba + minStart); break; default: _mesa_problem(ctx, "Bad min filter in sample_3d_texture"); return; } } if (magStart < magEnd) { /* do the magnified texels */ switch (tObj->MagFilter) { case GL_NEAREST: for (i = magStart; i < magEnd; i++) sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], texcoords[i], rgba[i]); break; case GL_LINEAR: for (i = magStart; i < magEnd; i++) sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], texcoords[i], rgba[i]); break; default: _mesa_problem(ctx, "Bad mag filter in sample_3d_texture"); return; } }}/**********************************************************************//* Texture Cube Map Sampling Functions *//**********************************************************************//** * Choose one of six sides of a texture cube map given the texture * coord (rx,ry,rz). Return pointer to corresponding array of texture * images. */static const struct gl_texture_image **choose_cube_face(const struct gl_texture_object *texObj, const GLfloat texcoord[4], GLfloat newCoord[4]){ /* major axis direction target sc tc ma ---------- ------------------------------- --- --- --- +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz */ const GLfloat rx = texcoord[0]; const GLfloat ry = texcoord[1]; const GLfloat rz = texcoord[2]; const GLfloat arx = FABSF(rx), ary = FABSF(ry), arz = FABSF(rz); GLuint face; GLfloat sc, tc, ma; if (arx > ary && arx > arz) { if (rx >= 0.0F) { face = FACE_POS_X; sc = -rz; tc = -ry; ma = arx; } else { face = FACE_NEG_X; sc = rz; tc = -ry; ma = arx; } } else if (ary > arx && ary > arz) { if (ry >= 0.0F) { face = FACE_POS_Y; sc = rx; tc = rz; ma = ary; } else { face = FACE_NEG_Y; sc = rx; tc = -rz; ma = ary; } } else { if (rz > 0.0F) { face = FACE_POS_Z; sc = rx; tc = -ry; ma = arz; } else { face = FACE_NEG_Z; sc = -rx; tc = -ry; ma = arz; } } newCoord[0] = ( sc / ma + 1.0F ) * 0.5F; newCoord[1] = ( tc / ma + 1.0F ) * 0.5F; return (const struct gl_texture_image **) texObj->Image[face];}static voidsample_nearest_cube(GLcontext *ctx, const struct gl_texture_object *tObj, GLuint n, const GLfloat texcoords[][4], const GLfloat lambda[], GLchan rgba[][4]){ GLuint i; (void) lambda; for (i = 0; i < n; i++) { const struct gl_texture_image **images; GLfloat newCoord[4]; images = choose_cube_face(tObj, texcoords[i], newCoord); sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel], newCoord, rgba[i]); }}static voidsample_linear_cube(GLcontext *ctx, const struct gl_texture_object *tObj, GLuint n, const GLfloat texcoords[][4], const GLfloat lambda[], GLchan rgba[][4]){ GLuint i; (void) lambda; for (i = 0; i < n; i++) { const struct gl_texture_image **images; GLfloat newCoord[4]; images = choose_cube_face(tObj, texcoords[i], newCoord); sample_2d_linear(ctx, tObj, images[tObj->BaseLevel], newCoord, rgba[i]); }}static voidsample_cube_nearest_mipmap_nearest(GLcontext *ctx, const struct gl_texture_object *tObj, GLuint n, const GLfloat texcoord[][4], const GLfloat lambda[], GLchan rgba[][4]){ GLuint i; ASSERT(lambda != NULL); for (i = 0; i < n; i++) { const struct gl_texture_image **images; GLfloat newCoord[4]; GLint level; images = choose_cube_face(tObj, texcoord[i], newCoord); /* XXX we actually need to recompute lambda here based on the newCoords. * But we would need the texcoords of adjacent fragments to compute that * properly, and we don't have those here. * For now, do an approximation: subtracting 1 from the chosen mipmap * level seems to work in some test cases. * The same adjustment is done in the next few functions. */ level = nearest_mipmap_level(tObj, lambda[i]); level = MAX2(level - 1, 0); sample_2d_nearest(ctx, tObj, images[level], newCoord, rgba[i]); }}static voidsample_cube_linear_mipmap_nearest(GLcontext *ctx, const struct gl_texture_object *tObj, GLuint n, const GLfloat texcoord[][4], const GLfloat lambda[], GLchan rgba[][4]){ GLuint i; ASSERT(lambda != NULL); for (i = 0; i < n; i++) { const struct gl_texture_image **images; GLfloat newCoord[4]; GLint level = nearest_mipmap_level(tObj, lambda[i]); level = MAX2(level - 1, 0); /* see comment above */ images = choose_cube_face(tObj, texcoord[i], newCoord); sample_2d_linear(ctx, tObj, images[level], newCoord, rgba[i]); }}static voidsample_cube_nearest_mipmap_linear(GLcontext *ctx, const struct gl_texture_object *tObj, GLuint n, const GLfloat texcoord[][4], const GLfloat lambda[], GLchan rgba[][4]){ GLuint i; ASSERT(lambda != NULL); for (i = 0; i < n; i++) { const struct gl_texture_image **images; GLfloat newCoord[4]; GLint level = linear_mipmap_level(tObj, lambda[i]); level = MAX2(level - 1, 0); /* see comment above */ images = choose_cube_face(tObj, texcoord[i], newCoord); if (level >= tObj->_MaxLevel) { sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel], newCoord, rgba[i]); } else { GLchan t0[4], t1[4]; /* texels */ const GLfloat f = FRAC(lambda[i]); sample_2d_nearest(ctx, tObj, images[level ], newCoord, t0); sample_2d_nearest(ctx, tObj, images[level+1], newCoord, t1); lerp_rgba(rgba[i], f, t0, t1); } }}static voidsample_cube_linear_mipmap_linear(GLcontext *ctx, const struct gl_texture_object *tObj, GLuint n, const GLfloat texcoord[][4], const GLfloat lambda[], GLchan rgba[][4]){ GLuint i; ASSERT(lambda != NULL); for (i = 0; i < n; i++) { const struct gl_texture_image **images; GLfloat newCoord[4]; GLint level = linear_mipmap_level(tObj, lambda[i]); level = MAX2(level - 1, 0); /* see comment above */ images = choose_cube_face(tObj, texcoord[i], newCoord); if (level >= tObj->_MaxLevel) { sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel], newCoord, rgba[i]); } else { GLchan t0[4], t1[4]; const GLfloat f = FRAC(lambda[i]); sample_2d_linear(ctx, tObj, images[level ], newCoord, t0); sample_2d_linear(ctx, tObj, images[level+1], newCoord, t1); lerp_rgba(rgba[i], f, t0, t1); } }}static voidsample_lambda_cube( GLcontext *ctx, const struct gl_texture_object *tObj, GLuint n, const GLfloat texcoords[][4], const GLfloat lambda[], GLchan rgba[][4]){ GLuint minStart, minEnd; /* texels with minification */ GLuint magStart, magEnd; /* texels with magnification */ ASSERT(lambda != NULL); compute_min_mag_ranges(tObj, n, lambda, &minStart, &minEnd, &magStart, &magEnd); if (minStart < minEnd) { /* do the minified texels */ const GLuint m = minEnd - minStart; switch (tObj->MinFilter) { case GL_NEAREST: sample_nearest_cube(ctx, tObj, m, texcoords + minStart, lambda + minStart, rgba + minStart); break; case GL_LINEAR: sample_linear_cube(ctx, tObj, m, texcoords + minStart, lambda + minStart, rgba + minStart); break; case GL_NEAREST_MIPMAP_NEAREST: sample_cube_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart, lambda + minStart, rgba + minStart); break; case GL_LINEAR_MIPMAP_NEAREST: sample_cube_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart, lambda + minStart, rgba + minStart); break; case GL_NEAREST_MIPMAP_LINEAR: sample_cube_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, lambda + minStart, rgba + minStart); break; case GL_LINEAR_MIPMAP_LINEAR: sample_cube_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart, lambda + minStart, rgba + minStart); break; default: _mesa_problem(ctx, "Bad min filter in sample_lambda_cube"); } } if (magStart < magEnd) { /* do the magnified texels */ const GLuint m = magEnd - magStart; switch (tObj->MagFilter) { case GL_NEAREST: sample_nearest_cube(ctx, tObj, m, texcoords + magStart, lambda + magStart, rgba + magStart); break; case GL_LINEAR: sample_linear_cube(ctx, tObj, m, texcoords + magStart, lambda + magStart, rgba + magStart); break; default: _mesa_problem(ctx, "Bad mag filter in sample_lambda_cube"); } }}/**********************************************************************//* Texture Rectangle Sampling Functions *//**********************************************************************//** * Do clamp/wrap for a texture rectangle coord, GL_NEAREST filter mode. */static INLINE GLintclamp_rect_coord_nearest(GLenum wrapMode, GLfloat coord, GLint max){ if (wrapMode == GL_CLAMP) { return IFLOOR( CLAMP(coord, 0.0F, max - 1) ); } else if (wrapMode == GL_CLAMP_TO_EDGE) { return IFLOOR( CLAMP(coord, 0.5F, max - 0.5F) ); } else { return IFLOOR( CLAMP(coord, -0.5F, max + 0.5F) ); }}/* * As above, but GL_LINEAR filtering. */static INLINE voidclamp_rect_coord_linear(GLenum wrapMode, GLfloat coord, GLint max, GLint *i0out, GLint *i1out){ GLfloat fcol; GLint i0, i1; if (wrapMode == GL_CLAMP)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -