osx - glTexSubImage2D shifting NSImage by a pixel -



osx - glTexSubImage2D shifting NSImage by a pixel -

i’m working on app creates it’s own texture atlas. elements on atlas can vary in size placed in grid pattern.

it’s working fine except fact when write on section of atlas new element (the info nsimage), image shifted pixel right.

the code i’m using write pixels onto atlas is:

-(void)writetoplatewithimage:(nsimage*)animage atcoord:(mygridpoint)gridpos; { static nssize insetsize; //ultimately size of image in box static nssize boundingbox; //this size of box holds image in grid static cgfloat multiplier; multiplier = 1.0; nssize platesize = nsmakesize(atlas.width, atlas.height);//size of entire atlas mygridpoint _gridpos; //make sure column , row position legal _gridpos.column= gridpos.column >= m_numofcolumns ? m_numofcolumns - 1 : gridpos.column; _gridpos.row = gridpos.row >= m_numofrows ? m_numofrows - 1 : gridpos.row; _gridpos.column = gridpos.column < 0 ? 0 : gridpos.column; _gridpos.row = gridpos.row < 0 ? 0 : gridpos.row; insetsize = nsmakesize(platesize.width / m_numofcolumns, platesize.height / m_numofrows); boundingbox = insetsize; //…code here calculate size create animage fits space allowed //on atlas. //multiplier var hold value sizes or downwards image… insetsize.width = animage.size.width * multiplier; insetsize.height = animage.size.height * multiplier; //provide padding around image when mipmaps created image doesn’t ‘bleed’ //if it’s same size grid’s boxes. insetsize.width -= ((insetsize.width * (insetpadding / 100)) * 2); insetsize.height -= ((insetsize.height * (insetpadding / 100)) * 2); //roundup() handy function found somewhere (i can’t remember now) //that makes first param multiple of the second.. //here create sure image lines aligned it’s rgba create //it multiple of 4 insetsize.width = (cgfloat)roundup((int)insetsize.width, 4); insetsize.height = (cgfloat)roundup((int)insetsize.height, 4); nsimage *insetimage = [self resizeimage:[animage copy] tosize:insetsize]; nsdata *insetdata = [insetimage tiffrepresentation]; glubyte *data = malloc(insetdata.length); memcpy(data, [insetdata bytes], insetdata.length); insetimage = null; insetdata = null; glenable(gl_texture_2d); glbindtexture(gl_texture_2d, atlas.textureindex); glpixelstorei(gl_unpack_alignment, 1); //have tried 2,4, , 8 glint xplace = (glint)(boundingbox.width * _gridpos.column) + (glint)((boundingbox.width - insetsize.width) / 2); glint yplace = (glint)(boundingbox.height * _gridpos.row) + (glint)((boundingbox.height - insetsize.height) / 2); gltexsubimage2d(gl_texture_2d, 0, xplace, yplace, (glsizei)insetsize.width, (glsizei)insetsize.height, gl_rgba, gl_unsigned_byte, data); glgeneratemipmap(gl_texture_2d); free(data); glbindtexture(gl_texture_2d, 0); glgeterror(); }

the images rgba, 8bit (as reported photoshop), here's test image i've been using:

and here's screen grab of result in app:

am unpacking image incorrectly...? know resizeimage: function works i've saved it's result disk bypassed problem somewhere in gl-code...

edit: clarify, section of atlas beingness rendered larger box diagram. shift occurring withing area that's written gltexsubimage2d.

edit 2: sorted, finally, offsetting copied info goes section of atlas.

i don't understand why is, perhaps it's hack instead of proper solution here is.

//resize image fit section of atlas nsimage *insetimage = [self resizeimage:[animage copy] tosize:nsmakesize(insetsize.width, insetsize.height)]; //pointer raw info const void* insetdataptr = [[insetimage tiffrepresentation] bytes]; //for debugging, placed offset value next int offset = 8;//it needed 2 pixel (2 * 4 byte rgba) offset //copy info offset temporary info buffer memcpy(data, insetdataptr + offset, insetdata.length - offset); /* . . calculate it's position texture . */ //and overwrite texture gltexsubimage2d(gl_texture_2d, 0, xplace, yplace, (glsizei)insetsize.width, (glsizei)insetsize.height, gl_rgba, gl_unsigned_byte, data);

you may running issue answered here: stackoverflow.com/a/5879551/524368

it's not pixel coordinates, pixel perfect addressing of texels. of import texture atlases. mutual misconception is, many people assume texture coordinates 0 , 1 come lie on pixel centers. in opengl not case, texture coordinates 0 , 1 on border between pixels of texture wrap. if build texture atlas making 0 , 1 on pixel centers assumption, using same addressing scheme in opengl lead either blurry image or pixel shifts. need business relationship this.

i still don't understand how makes difference sub-section of texture that's beingness rendered.

it helps lot understand opengl textures not much images rather back upwards samples interpolator (hence "sampler" uniforms in shaders). crisp looking images you've take texture coordinates you're sampling in way, interpolator evaluates @ exactly position of back upwards samples. position of samples neither integer coordinates nor fractions (i/n).

note newer versions of glsl provide texture sampling function texelfetch bypasses interpolator , addresses texture pixels directly. if need pixel perfect texturing might find easier utilize (if available).

osx cocoa opengl

Comments

Popular posts from this blog

php - Android app custom user registration and login with cookie using facebook sdk -

django - Access session in user model .save() -

php - .htaccess Multiple Rewrite Rules / Prioritizing -