bilinear sampling of depth textures

This commit is contained in:
Brian Paul
2001-02-26 18:24:37 +00:00
parent feca368c29
commit 30038ecaa2

View File

@@ -1,4 +1,4 @@
/* $Id: s_texture.c,v 1.12 2001/02/20 16:42:26 brianp Exp $ */
/* $Id: s_texture.c,v 1.13 2001/02/26 18:24:37 brianp Exp $ */
/*
* Mesa 3-D graphics library
@@ -49,6 +49,13 @@
/*
* Used to compute texel locations for linear sampling.
* Input:
* wrapMode = GL_REPEAT, GL_CLAMP or GL_CLAMP_TO_EDGE
* S = texcoord in [0,1]
* SIZE = width (or height or depth) of texture
* Output:
* U = texcoord in [0, width]
* I0, I1 = two nearest texel indexes
*/
#define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
{ \
@@ -2341,12 +2348,12 @@ apply_texture( const GLcontext *ctx,
/*
* Apply a shadow/depth texture to the array of colors.
* Sample a shadow/depth texture.
* Input: ctx - context
* texUnit - the texture unit
* n - number of colors
* r - array [n] of texture R coordinates
* In/Out: rgba - array [n] of colors.
* n - number of samples
* s,t,r - array [n] of texture coordinates
* In/Out: rgba - array [n] of texel colors.
*/
static void
sample_depth_texture(const GLcontext *ctx,
@@ -2356,10 +2363,31 @@ sample_depth_texture(const GLcontext *ctx,
GLchan texel[][4])
{
const struct gl_texture_object *texObj = texUnit->_Current;
const struct gl_texture_image *texImage = texObj->Image[0]; /* XXX hack */
const GLint baseLevel = texObj->BaseLevel;
const struct gl_texture_image *texImage = texObj->Image[baseLevel];
const GLuint width = texImage->Width;
const GLuint height = texImage->Height;
const GLchan ambient = texObj->ShadowAmbient;
GLboolean lequal, gequal;
GLuint i;
if (texObj->Dimensions != 2) {
gl_problem(ctx, "only 2-D depth textures supported at this time");
return;
}
if (texObj->MinFilter != texObj->MagFilter) {
gl_problem(ctx, "mipmapped depth textures not supported at this time");
return;
}
/* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
* GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
* isn't a depth texture.
*/
if (texImage->Format != GL_DEPTH_COMPONENT) {
gl_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
return;
}
if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
lequal = GL_TRUE;
@@ -2370,35 +2398,229 @@ sample_depth_texture(const GLcontext *ctx,
gequal = GL_TRUE;
}
assert(texObj->Dimensions == 2);
assert(texImage->Format == GL_DEPTH_COMPONENT);
for (i = 0; i < n; i++) {
const GLfloat *src;
GLfloat depthSample;
GLint col, row;
/* XXX this is a hack - implement proper sampling */
COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, s[i], texImage->Width, col);
COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, t[i], texImage->Height,row);
src = (const GLfloat *) texImage->Data + row * texImage->Width + col;
depthSample = *src;
if ((depthSample <= r[i] && lequal) ||
(depthSample >= r[i] && gequal)) {
texel[i][RCOMP] = ambient;
texel[i][GCOMP] = ambient;
texel[i][BCOMP] = ambient;
texel[i][ACOMP] = CHAN_MAX;
if (texObj->MagFilter == GL_NEAREST) {
GLuint i;
for (i = 0; i < n; i++) {
GLfloat depthSample;
GLint col, row;
COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, s[i], width, col);
COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, t[i], height, row);
depthSample = *((const GLfloat *) texImage->Data + row * width + col);
if ((depthSample <= r[i] && lequal) ||
(depthSample >= r[i] && gequal)) {
texel[i][RCOMP] = ambient;
texel[i][GCOMP] = ambient;
texel[i][BCOMP] = ambient;
texel[i][ACOMP] = CHAN_MAX;
}
else {
texel[i][RCOMP] = CHAN_MAX;
texel[i][GCOMP] = CHAN_MAX;
texel[i][BCOMP] = CHAN_MAX;
texel[i][ACOMP] = CHAN_MAX;
}
}
else {
texel[i][RCOMP] = CHAN_MAX;
texel[i][GCOMP] = CHAN_MAX;
texel[i][BCOMP] = CHAN_MAX;
texel[i][ACOMP] = CHAN_MAX;
}
else {
GLuint i;
ASSERT(texObj->MagFilter == GL_LINEAR);
for (i = 0; i < n; i++) {
GLfloat depth00, depth01, depth10, depth11;
GLint i0, i1, j0, j1;
GLfloat u, v;
GLuint useBorderTexel;
COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj->WrapS, s[i], u, width, i0, i1);
COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj->WrapT, t[i], v, height,j0, j1);
useBorderTexel = 0;
if (texImage->Border) {
i0 += texImage->Border;
i1 += texImage->Border;
j0 += texImage->Border;
j1 += texImage->Border;
}
else {
if (i0 < 0 || i0 >= width) useBorderTexel |= I0BIT;
if (i1 < 0 || i1 >= width) useBorderTexel |= I1BIT;
if (j0 < 0 || j0 >= height) useBorderTexel |= J0BIT;
if (j1 < 0 || j1 >= height) useBorderTexel |= J1BIT;
}
/* get four depth samples from the texture */
if (useBorderTexel & (I0BIT | J0BIT)) {
depth00 = 1.0;
}
else {
depth00 = *((const GLfloat *) texImage->Data + j0 * width + i0);
}
if (useBorderTexel & (I1BIT | J0BIT)) {
depth10 = 1.0;
}
else {
depth10 = *((const GLfloat *) texImage->Data + j0 * width + i1);
}
if (useBorderTexel & (I0BIT | J1BIT)) {
depth01 = 1.0;
}
else {
depth01 = *((const GLfloat *) texImage->Data + j1 * width + i0);
}
if (useBorderTexel & (I1BIT | J1BIT)) {
depth11 = 1.0;
}
else {
depth11 = *((const GLfloat *) texImage->Data + j1 * width + i1);
}
if (0) {
/* compute a single weighted depth sample and do one comparison */
const GLfloat a = FRAC(u);
const GLfloat b = FRAC(v);
const GLfloat w00 = (1.0F - a) * (1.0F - b);
const GLfloat w10 = ( a) * (1.0F - b);
const GLfloat w01 = (1.0F - a) * ( b);
const GLfloat w11 = ( a) * ( b);
const GLfloat depthSample = w00 * depth00 + w10 * depth10
+ w01 * depth01 + w11 * depth11;
if ((depthSample <= r[i] && lequal) ||
(depthSample >= r[i] && gequal)) {
texel[i][RCOMP] = ambient;
texel[i][GCOMP] = ambient;
texel[i][BCOMP] = ambient;
texel[i][ACOMP] = CHAN_MAX;
}
else {
texel[i][RCOMP] = CHAN_MAX;
texel[i][GCOMP] = CHAN_MAX;
texel[i][BCOMP] = CHAN_MAX;
texel[i][ACOMP] = CHAN_MAX;
}
}
else {
/* Do four depth/R comparisons and compute a weighted result.
* If this touches on somebody's I.P., I'll remove this code
* upon request.
*/
const GLfloat d = (CHAN_MAXF - (GLfloat) ambient) * 0.25F;
GLfloat luminance = CHAN_MAXF;
GLchan lum;
if (lequal) {
if (depth00 <= r[i]) luminance -= d;
if (depth01 <= r[i]) luminance -= d;
if (depth10 <= r[i]) luminance -= d;
if (depth11 <= r[i]) luminance -= d;
}
else {
if (depth00 >= r[i]) luminance -= d;
if (depth01 >= r[i]) luminance -= d;
if (depth10 >= r[i]) luminance -= d;
if (depth11 >= r[i]) luminance -= d;
}
lum = (GLchan) luminance;
texel[i][RCOMP] = lum;
texel[i][GCOMP] = lum;
texel[i][BCOMP] = lum;
texel[i][ACOMP] = CHAN_MAX;
}
}
}
}
#if 0
/*
* Experimental depth texture sampling function.
*/
static void
sample_depth_texture2(const GLcontext *ctx,
const struct gl_texture_unit *texUnit,
GLuint n,
const GLfloat s[], const GLfloat t[], const GLfloat r[],
GLchan texel[][4])
{
const struct gl_texture_object *texObj = texUnit->_Current;
const GLint baseLevel = texObj->BaseLevel;
const struct gl_texture_image *texImage = texObj->Image[baseLevel];
const GLuint width = texImage->Width;
const GLuint height = texImage->Height;
const GLchan ambient = texObj->ShadowAmbient;
GLboolean lequal, gequal;
if (texObj->Dimensions != 2) {
gl_problem(ctx, "only 2-D depth textures supported at this time");
return;
}
if (texObj->MinFilter != texObj->MagFilter) {
gl_problem(ctx, "mipmapped depth textures not supported at this time");
return;
}
/* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
* GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
* isn't a depth texture.
*/
if (texImage->Format != GL_DEPTH_COMPONENT) {
gl_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
return;
}
if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
lequal = GL_TRUE;
gequal = GL_FALSE;
}
else {
lequal = GL_FALSE;
gequal = GL_TRUE;
}
{
GLuint i;
for (i = 0; i < n; i++) {
const GLint K = 3;
GLint col, row, ii, jj, imin, imax, jmin, jmax, samples, count;
GLfloat w;
GLchan lum;
COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, s[i], width, col);
COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, t[i], height, row);
imin = col - K;
imax = col + K;
jmin = row - K;
jmax = row + K;
if (imin < 0) imin = 0;
if (imax >= width) imax = width - 1;
if (jmin < 0) jmin = 0;
if (jmax >= height) jmax = height - 1;
samples = (imax - imin + 1) * (jmax - jmin + 1);
count = 0;
for (jj = jmin; jj <= jmax; jj++) {
for (ii = imin; ii <= imax; ii++) {
GLfloat depthSample = *((const GLfloat *) texImage->Data
+ jj * width + ii);
if ((depthSample <= r[i] && lequal) ||
(depthSample >= r[i] && gequal)) {
count++;
}
}
}
w = (GLfloat) count / (GLfloat) samples;
w = CHAN_MAXF - w * (CHAN_MAXF - (GLfloat) ambient);
lum = (GLint) w;
texel[i][RCOMP] = lum;
texel[i][GCOMP] = lum;
texel[i][BCOMP] = lum;
texel[i][ACOMP] = CHAN_MAX;
}
}
}
#endif
/*
* Apply a unit of texture mapping to the incoming fragments.