Re: clip texture LOD offset trouble

New Message Reply Date view Thread view Subject view Author view

Don Hatch (hatch++at++hell.engr.sgi.com)
Mon, 4 Jan 1999 22:44:42 -0800


On Jan 4, 8:20am, Wear, Mark wrote:
> Subject: clip texture LOD offset trouble
> Happy New Year!
>
> In my application, I use a precull callback to set the virtual LOD offset
> for each geode that is drawn. I end up using about 5 different offsets in
> any given frame. The approach works well, but I am seeing some texture
> artifacts in the scene. At a fairly constant distance from the eyepoint,
> texture tiles (maybe only 1?) that appear to be incorrectly placed are
> being blended with the surrounding correctly-placed tiles. The result is an
> artifact in the distance that disappears as the eyepoint approaches it.
> Often, the incorrect tiles are completely black giving the appearance of
> rips in the texture. Sometimes however, the tiles are clearly texture from
> some other part of the database. This tile that does not belong is rendered
> and blended with its neighbors from other levels. This blending helps mask
> the problem, but the artifacts are significant enough to render this
> approach unusable.
>
> Some of the artifacts appear the be transient, eventually correcting
> themselves without eyepoint movement, but this is not always the case. These
> incorrectly placed tiles do not appear in an over-head view, only in more
> oblique views do they become a problem.
>
> Running the same application using only a single offset for all of the
> geodes eliminates the artifacts. Reducing the number of different offsets
> (down to 2) does not eliminate the problem. I have tried different blending
> techniques without improvement.
>
> I have read section 1.1 (Virtual clipmap alignment granularity vs. number of
> good levels) of the IR Virtual Clipmapping Bugs and Limitations document.
> I'm not sure if this is what I am seeing, or exactly what this document is
> saying.
>
> Here are a few questions. I hope someone has had similar experiences.
>
> Is there some texture mapping calculation that depends upon the LOD offset
> that could be using an incorrect offset value because I change it from geode
> to geode? (I think the problem would be much worse if this were the case.)
>
> What exactly is section 1.1 (Virtual clipmap alignment granularity vs.
> number of good levels) of the IR Virtual Clipmapping Bugs and Limitations
> document saying, and if that is my problem what can I do about it?
>
>
> System:
> Onyx II
> 512 MB
>
> As always, any help would be appreciated.
>
>
> Mark E. Wear
> Electronic Systems Engineer: Real-Time Simulation
> Lockheed Martin Vought Systems
> (972) 603-2758
> mark.wear++at++lmco.com
> =======================================================================

I'd suspect one of the following problems:

    1. Cull sorting may be scrambling the order of
       the geodes with respect to the LOD Offset calls to OpenGL.

       If this is the problem, you should be able to verify
       that it goes away when you set Cull Mode to "None" (if you
       have a perfly- or clipfly-based application).
       The most common cause of this is if you forgot
       to do the following on each of the geodes,
       as explained in the HowToDoVirtual.html doc:
             geode->setTravMode(PFTRAV_CULL,
                                PFTRAV_CULL_SORT,
                                PFN_CULL_SORT_CONTAINED);

    2. If the clipsize/2-sized level is not loaded all in one
       piece, it comes out as garbage.
       (This is an OpenGL bug, described in section 2.4
       in the IRClipmapBugs.html doc).
       If this is the problem, you should be able to verify that it's
       only happening on that one level by turning on Gridify
       (to color-code the levels) and fiddling
       with the Min&Max LOD sliders to isolate the levels being viewed.
       If this is the problem, you need to change your configuration files
       so that that level consists of only a single image tile
       (either make that level actually be an image tile, or make that level
       be an image cache consisting of a single image tile).
       Unfortunately this is incompatible with the new "no-.ic" .ct
       configuration files if you want to use a global tile
       size that's smaller than clipsize/2.
       The possible workarounds are to switch to a global tile size
       of clipsize/2 or bigger,
       or use the old .ct format that lets you configure each
       level separately and make that "problem" level's tile size
       be equal to its level size
       (of course, you will have to regenerate your image tile files
       to use the larger tile size for at least that level,
       or for all the levels, depending on which workaround you use).

       Actually, now that I think about it, you may be
       able to get around this and still use the simpler no-.ic format,
       by setting smallest_icache to be equal to
       clip_size; hopefully this will force
       all smaller levels (in particular the problem level),
       to consist of a single image tile per level.
       If you try this, and it works, please report back--
       it will make a lot of peoples' lives easier!

    3. One or more levels may be configured badly or have bad data.
       Again, you should be able to verify/test this
       by turning on Gridify and using the Min&Max LOD sliders
       to isolate the bad level(s).

    4. The Granularity vs. number of Good levels problem you mentioned.
       Sorry, upon re-reading that section I see that it doesn't
       reflect the current situation very well.
       The IR OpenGL patches described in 2.1 use a heuristic
       that makes things work in most situations,
       but it's still wacky, and I've seen it mess up.
       If this is the cause of your problem,
       it should go away if you increase the invalid border,
       strange as that sounds. Increase it from 8 to 16, 32, 64, ...
       the smallest value that fixes your problem, if any.
       This workaround is probably the best you are going to be able to get
       if this is the problem.

While debugging this,
y ou might want to run "trashtexmem" or a similar program
that clears texture memory between your program runs,
so that you don't see leftover texture data from previous runs,
which can be confusing and misleading.
I'm including the program trashtexmem.c as an attachment.

Don

-- 
Don Hatch  hatch++at++sgi.com  (650) 933-5150  Silicon Graphics, Inc.

/* * file: trashtexmem.c * ------------------- * * A testing utility to all of trash texture memory. * Default behavior is to compute max texture size for a * 3 component texture and then to create, apply, and * display a red RGB bilinear texture. * * $Revision: 1.5 $ * $Date: 1998/04/30 21:34:19 $ * * cmdline-time controls: * -c numComp - set number of components * -d - toggle display mode (default is on) * -p r,g,b,a - specify all 4 rgba colors in hex [0,255] * -s sx,sy - set size of texture * */

#include <stdio.h> #include <stdlib.h> #include <getopt.h> /* for cmdline handler */ #include <ctype.h>

#include <Performer/pr.h>

#define MAX_TEX 64

int showTex = 1; int cmp = 4; int sx[MAX_TEX] = {-1}, sy[MAX_TEX] = {-1}; int wsx=10, wsy=10; pfTexture *tex[MAX_TEX]; unsigned char clr[4] = {0xff, 0, 0, 0xff};

pfVec4 white = {1, 1, 1, 1}; pfVec4 black = {0, 0, 0, 1};

pfVec3 coords[] ={ {-1.0f, -1.0f, 0.0f }, { 1.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 0.0f }, {-1.0f, 1.0f, 0.0f } };

static char ProgName[PF_MAXSTRING];

static void usage(void) { fprintf(stderr,"%s: [-p r,g,b,a] [-c cmp] [-s sx,sy] [-d]", ProgName); }

static int findTexSize(int bytes, int cmp, int *sx, int *sy) { int x=1, y=1, max;

/* assuming 2 bytes per texel, find max texture bytes */ max = bytes >> 1; if (!max) return 0;

/* find bigest square texture */ *sx = x; *sy = y; while (x * y <= max) { *sx = x; *sy = y; x <<= 1; y <<= 1; /*pfNotify(PFNFY_NOTICE,PFNFY_PRINT, "SQUARE: %d %d %d %d", x, y, x*y, max);*/ } pfNotify(PFNFY_NOTICE,PFNFY_PRINT, "FINAL: %d %d %d %d", *sx, *sy, *sx * *sy, max); return (*sx * *sy * 2); }

static void doShowTex(pfTexture *tex) { pfFrustum *frust; pfGeoSet *gset;

frust = pfNewFrust(NULL); pfMakeOrthoFrust(frust, -1, 1, -1, 1); pfFrustNearFar(frust, -1, 1); pfApplyFrust(frust); pfDelete(frust);

pfClear(PFCL_COLOR | PFCL_DEPTH, black);

/* Set up a geoset */ gset = pfNewGSet(NULL); pfGSetAttr(gset, PFGS_COORD3, PFGS_PER_VERTEX, coords, NULL); pfGSetAttr(gset, PFGS_COLOR4, PFGS_OVERALL, white, NULL); pfGSetPrimType(gset, PFGS_QUADS); pfGSetNumPrims(gset, 1);

pfDrawGSet(gset); }

static int docmdline(int argc, char *argv[]) { int opt; int lclr[4];

strcpy(ProgName, argv[0]);

/* process command-line arguments */ while ((opt = getopt(argc, argv, "c:dp:s:?")) != -1) { switch (opt) { case 'c': cmp = atoi(optarg); break; case 'd': showTex ^= 1; break; case 'p': sscanf(optarg,"0x%x,0x%x,0x%x,0x%x",&lclr[0], &lclr[1], &lclr[2], &lclr[3]); clr[0] = lclr[0]; clr[1] = lclr[1]; clr[2] = lclr[2]; clr[3] = lclr[3]; break; case 's': sscanf(optarg,"%d,%d", &sx, &sy); break; case '?': usage(); break; } } return optind; }

int main (int argc, char **argv) { unsigned char *data; unsigned int *ptr, *end; unsigned int clr_int; pfWindow *win; int s, b; int i; int numTex = 0;

docmdline(argc, argv);

/* Initialize Performer */ pfInit(); pfInitState(NULL);

pfNotify(PFNFY_NOTICE,PFNFY_MORE,"Mach String: %s", pfGetMachString());

pfQuerySys(PFQSYS_TEXTURE_MEMORY_BYTES,&b); pfNotify(PFNFY_NOTICE,PFNFY_MORE,"\tTEXTURE_MEMORY_BYTES: %d", b);

pfQuerySys(PFQSYS_MAX_TEXTURE_SIZE,&s); pfNotify(PFNFY_NOTICE,PFNFY_MORE,"\tMAX_TEXTURE_SIZE: %d", s);

if (sx[0] < 0) { while(b) { int t; t = findTexSize(b, cmp, &sx[numTex], &sy[numTex]); if (!t) { pfNotify(PFNFY_NOTICE,PFNFY_PRINT, "Woops - %d bytes NOT trashed", b); b = 0; continue; } pfNotify(PFNFY_NOTICE,PFNFY_PRINT, "Making %d comp texture of size %dx%d", cmp, sx[numTex], sy[numTex]); tex[numTex] = pfNewTex(NULL); pfTexFilter(tex[numTex], PFTEX_MINFILTER, PFTEX_BILINEAR); numTex++; b -= t; if (b < 0) { pfNotify(PFNFY_NOTICE,PFNFY_PRINT, "Woops - negative bytes: %d", b); b = 0; } } pfNotify(PFNFY_NOTICE,PFNFY_PRINT, "Made %d textures", numTex); }

s = sx[0]*sy[0]; data = pfMalloc(s*sizeof(unsigned int), NULL); ptr = (unsigned int *)data; /* Don't worry, the div by 4 will get lowered to a shift by the compiler */ end = ptr + s; clr_int = *(unsigned int *)clr; while (ptr < end) { /* I'm assuming that the color has 4 components, but this assumption exists elsewhere in this code. */ *ptr = clr_int; ptr++; } for (i=0; i < numTex; i++) pfTexImage(tex[i], (uint*) data, cmp, sx[i], sy[i], 0);

/* Initialize GL */ win = pfNewWin(NULL); pfWinName(win, "Iris Performer"); pfWinType(win, PFWIN_TYPE_X); if (showTex) { int maxX, maxY; pfGetScreenSize(-1, &maxX, &maxY); wsx = sx[0]; wsy = sy[0]; if (wsx > maxX) wsx = maxX; if (wsy > maxY) wsy = maxY; } pfWinOriginSize(win, 0, 0, wsx, wsy); pfOpenWin(win);

pfEnable(PFEN_TEXTURE); pfApplyTEnv(pfNewTEnv(NULL));

for (i=0; i < numTex; i++) { pfNotify(PFNFY_NOTICE,PFNFY_PRINT,"Loading tex %d", i); pfApplyTex(tex[i]); }

for (i=0; i < numTex; i++) { if (!pfIsTexLoaded(tex[i])) pfNotify(PFNFY_NOTICE,PFNFY_PRINT,"WOOPS - tex %d is NOT resident", i); if (showTex) doShowTex(tex[i]); }

#ifndef IRISGL { int err; if ((err = glGetError()) != GL_NO_ERROR) pfNotify(PFNFY_NOTICE,PFNFY_USAGE,"OpenGL Error 0x%x - %s",err, gluErrorString(err)); } #endif /* GL Type */

if (showTex) { pfSwapWinBuffers(win); sleep(1); } exit(0); }


New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2.0b2 on Mon Jan 04 1999 - 22:44:46 PST

This message has been cleansed for anti-spam protection. Replace '++at++' in any mail addresses with the '@' symbol.