Jump to content
  • Advertisement
Sign in to follow this  
coolkehon

OpenGL Drawing Images and Being able to modify them

This topic is 3253 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I learned the psp's gu which is very similar to opengl and now i'm switching to opengl and the way that textures i loaded on the psp is different from opengl. i have an image class i created to holds the image data then renders it by uploading the texture and palette (if any) then draws the coordinates. I've looked at tutorials (nehe +some) and i see that i need to define and object or id and opengl will keep the texture so i should free the texture data i have loaded. my question is where does that texture go and if i should decide to modify the pixel data of that texture how can i do that. also how do i load data into vram in opengl. by the way i'm using SDL for my opengl setup because it's cross platform

Share this post


Link to post
Share on other sites
Advertisement
Texture pixel data is usually stored in VRAM, and swapped to RAM when necessary.

To update a texture, you can use glTexImage1D/2D/3D to respecifiy texture data completely, or glTexSubImage1D/2D/3D to update a region of the texture data.

Share this post


Link to post
Share on other sites
what if i want my data to reside in ram. and how can i modify just a part of it. i would like to be able to modify the entire image

Share this post


Link to post
Share on other sites
also what is the maximum texture size for opengl if any because i know the psp has a max blitting size of 512x512 and the textures need to be in a power of two which i hate and a max texture size of 1028(?)x1028(?) i know it's 1000 something i believe but i really hope opengl doesnt have this problem and doesnt have that power of two problem either

Share this post


Link to post
Share on other sites
Again, use glTexSubImage1D/2D/3D to upload your modification to the texture in VRAM.

For maximum texture sizes, that's implementation dependant, you can query the maximum with glGetIntegerv(GL_MAX_TEXTURE_SIZE, &i); DX10 GPUs support 8192x8192, DX9.0c GPUs support mostly 4096x4096, etc.

For NPOT textures, you need GL 2.0 or the GL_ARB_texture_non_power_of_two extension.

Share this post


Link to post
Share on other sites
how do i get the gl version and how do i use gltexsubimage can you provide an example and here is my image class (modified a wee bit) from the psp it's very simple. could someone help me modify this to get it working on opengl

header

/*
* Image.h
*
* Created on: Jul 7, 2009
* Author: kurt
*/


#ifndef IMAGE_H_
#define IMAGE_H_

#include "Resizable2DInterface.h"

namespace objdraw
{

class Image: public objdraw::Resizable2DInterface
{
public:
typedef struct PaletteData
{
bool in_vram;
short pixelFormat;
short nentries;
unsigned int * data;
unsigned int size;
} __PaletteData;

typedef struct ImageData
{
bool in_vram;
bool swizzled;
short pixelFormat;
int width;
int height;
int textureWidth;// the real width of data, 2^n with n>=0
int textureHeight; // the real height of data, 2^n with n>=0
unsigned int * data;
unsigned int size;
PaletteData * palette;
} __ImageData;
protected:
virtual ~Image();
std::string error;
bool mirroredVert, mirroredHori;
public:
ImageData * image;
static PaletteData * CreatePalette(int size, bool in_vram, short pixelFormat);

// Image();
Image(Image const & r);
Image(DrawingCanvas * c = NULL);

virtual void render();
virtual void render_big();

uint getPixel(uint x, uint y);
void setPixel(uint x, uint y, uint pixel);

uint getImageWidth();
uint getImageHeigth();

virtual void swizzle();
virtual void unswizzle();
virtual bool swizzled();

bool isMirroredVert();
bool isMirroredHori();
void mirrorVert();
void mirrorHori();
void setVertMirror(bool mir);
void setHoriMirror(bool mir);
// TODO virtual std::string toString();
friend class ImageUtil;
};

}

#endif /* IMAGE_H_ */




.cpp file (source)

/*
* Image.cpp
*
* Created on: Jul 7, 2009
* Author: kurt
*/


#include "Image.h"
#include "DrawingCanvas.h"
#include "Types.h"
#include "GraphicsInstance.h"
#include <GL/gl.h>
#include <malloc.h>
#include <cstring>
#include <sstream>
#include <math.h>
#include "ImageUtil.h"
using namespace std;
using namespace objdraw;

Image::PaletteData * Image::CreatePalette(int size, bool in_vram, short pixelFormat)
{
PaletteData * palette = (Image::PaletteData *)malloc(sizeof(Image::PaletteData));
if(palette == NULL)
return NULL;
palette->pixelFormat = pixelFormat;
palette->nentries = size;
palette->in_vram = in_vram;
palette->size = (palette->nentries * ImageUtil::paletteSizes[pixelFormat]) >> 3;
if(!in_vram)
palette->data = (uint *)memalign(16,palette->size);
else
palette->data = (uint *)valloc(palette->size);
if(palette->data == NULL)
{
free(palette);
return NULL;
}
memset(palette->data,0,palette->size);
return palette;
}

Image::~Image()
{
if(image != NULL)
{
if(image->data != NULL)
{
if(image->in_vram)
vfree(image->data);
else
free(image->data);
}
if(image->palette != NULL)
{
if(image->palette->data != NULL)
{
if(image->palette->in_vram)
vfree(image->palette->data);
else
free(image->palette->data);
}
free(image->palette);
}
free(image);
image = NULL;
}
}
//Image::Image()
//{
// start = Location(0,0);
// end = Location(0,0);
// color = Color(0,0,0);
// hidden = false;
// image = NULL;
// canvas = NULL;
// mirroredVert = mirroredHori = false;
//}
Image::Image(Image const & r)
{
start = r.start;
end = r.end;
color = r.color;
hidden = r.hidden;
canvas = r.canvas;
mirroredVert = r.mirroredVert;
mirroredHori = r.mirroredHori;

image = NULL;
if(r.image != NULL)
{
image = (ImageData *)malloc(sizeof(ImageData));
if(image == NULL)
return;
memcpy(image,r.image,sizeof(ImageData));
image->in_vram = false;
image->data = NULL;
image->palette = NULL;
if(r.image->data != NULL)
{
int size = r.image->size;
if(r.image->in_vram)
{
image->data = (unsigned int *)valloc(size);
if(image->data != NULL)
image->in_vram = true;
}
if(image->data == NULL)
image->data = (unsigned int *)memalign(16,size);
if(image->data != NULL)
memcpy(image->data,r.image->data,size);
}
if(r.image->palette != NULL)
{
image->palette = (PaletteData *)malloc(sizeof(PaletteData));
if(image->palette != NULL)
{
if(r.image->palette->in_vram)
image->palette->data = (unsigned int *)valloc(sizeof(r.image->palette->size));
else
image->palette->data = (unsigned int *)memalign(16,sizeof(r.image->palette->size));
if(image->palette->data != NULL)
{
memcpy(image->palette->data,r.image->palette->data,r.image->palette->size);
image->palette->nentries = r.image->palette->nentries;
image->palette->pixelFormat = r.image->palette->pixelFormat;
image->palette->size = r.image->palette->size;
}
}
}
}
if(canvas != NULL)
canvas->getCanvasContent().addDrawable(this);
}
Image::Image(DrawingCanvas * c)
{
start = Location(0,0);
end = Location(0,0);
color = Color(0,0,0);
hidden = false;
image = NULL;
canvas = c;
mirroredVert = mirroredHori = false;
if(canvas != NULL)
canvas->getCanvasContent().addDrawable(this);
}
uint Image::getPixel(uint x, uint y)
{
// TODO get swizzled pixel address
if(swizzled() || image == NULL || image->data == NULL)
return 0;
int index = (y * image->width) + x;
if(index >= image->size)
return 0;
return image->data[index];
}
void Image::setPixel(uint x, uint y, uint pixel)
{
// TODO get swizzled pixel address
if(swizzled() || image == NULL || image->data == NULL)
return;
int index = (y * image->width) + x;
if(index >= image->size)
return;
image->data[index] = pixel;
}
uint Image::getImageWidth()
{
if(image != NULL && image->data != NULL)
return image->width;
return 0;
}
uint Image::getImageHeigth()
{
if(image != NULL && image->data != NULL)
return image->height;
return 0;
}
void Image::swizzle()
{
if(image == NULL)
return;
if(image->data == NULL || image->swizzled)
return;

int _alignWidth = image->textureWidth;
int _alignHeight = image->textureHeight;
u32 * _data = (u32 *)image->data;

unsigned int swizwidth = (_alignWidth * sizeof(u32));
u32 * temp = (u32 *)memalign(16, _alignHeight * swizwidth);

if(temp == NULL)
return;

unsigned int blockx, blocky;
unsigned int j;
unsigned int width_blocks = swizwidth >> 4;
unsigned int height_blocks = _alignHeight >> 3;
unsigned int src_pitch = (swizwidth - 16) >> 2;
unsigned int src_row = swizwidth << 3;
const u8* ysrc = (u8*)_data;
u32* dst = temp;
for(blocky = 0; blocky < height_blocks; ++blocky)
{
const u8* xsrc = ysrc;
for(blockx = 0; blockx < width_blocks; ++blockx)
{
const u32* src = (u32*)xsrc;
for(j = 0; j < 8; ++j)
{
*(dst++) = *(src++);
*(dst++) = *(src++);
*(dst++) = *(src++);
*(dst++) = *(src++);
src += src_pitch;
}
xsrc += 16;
}
ysrc += src_row;
}
free(_data);
image->data = temp;
image->swizzled = true;
sceKernelDcacheWritebackAll();
}
void Image::unswizzle()
{
if(image == NULL)
return;
if(image->data == NULL || !image->swizzled)
return;

int _alignWidth = image->textureWidth;
int _alignHeight = image->textureHeight;
u32 * _data = (u32 *)image->data;

unsigned int swizwidth = (_alignWidth * sizeof(u32));

u32 * temp = (u32 *)memalign(16, swizwidth * _alignHeight);
if(temp == NULL)
return;

unsigned int blockx, blocky;
unsigned int j;
unsigned int width_blocks = swizwidth >> 4;
unsigned int height_blocks = _alignHeight >> 3;
unsigned int dst_pitch = (swizwidth - 16) >> 2;
unsigned int dst_row = swizwidth << 3;

const u8* ydst = (u8*)temp;
u32* src = _data;

for(blocky = 0; blocky < height_blocks; ++blocky)
{
const u8* xdst = ydst;
for(blockx = 0; blockx < width_blocks; ++blockx)
{
u32* dst = (u32*)xdst;
for(j = 0; j < 8; ++j)
{
*(dst++) = *(src++);
*(dst++) = *(src++);
*(dst++) = *(src++);
*(dst++) = *(src++);
dst += dst_pitch;
}
xdst += 16;
}
ydst += dst_row;
}
free(_data);
image->data = temp;
image->swizzled = false;
sceKernelDcacheWritebackAll();
}
bool Image::swizzled()
{
if(image != NULL)
return image->swizzled;
return false;
}
bool Image::isMirroredVert()
{
return mirroredVert;
}
bool Image::isMirroredHori()
{
return mirroredHori;
}
void Image::mirrorVert()
{
mirroredVert = true;
}
void Image::mirrorHori()
{
mirroredHori = true;
}
void Image::setVertMirror(bool mir)
{
mirroredVert = mir;
}
void Image::setHoriMirror(bool mir)
{
mirroredHori = mir;
}
void Image::render_big()
{
if(hidden || !(image != NULL && image->data != NULL))
return;
if(image->textureHeight < 512 && image->textureWidth < 512)
{
render();
return;
}

sceGuDisable(GU_DEPTH_TEST);
sceGuEnable(GU_TEXTURE_2D);
if(image->palette != NULL)
{
if(image->palette->data != NULL)
{
// upload palette
sceGuClutMode(image->palette->pixelFormat,0,0xff,0);
sceGuClutLoad((image->palette->nentries>>3), image->palette->data);
}
}
// setting the texture
sceGuTexMode(image->pixelFormat,0,0,image->swizzled);
sceGuTexFilter( GU_LINEAR, GU_LINEAR );
sceGuTexFunc(GU_TFX_REPLACE, image->pixelFormat == GU_PSM_5650 ? GU_TCC_RGB : GU_TCC_RGBA);
sceGuTexImage(0, image->textureWidth, image->textureHeight, image->textureWidth, image->data);

int slice = 64;
int sliceWidth = slice;
int width = getWidth();
int height = getHeight();
int dx = start.x, dy = start.y, sx = 0, sy = 0;

for(int j = 0; j < width; j += sliceWidth)
{

vertex2d * points = (vertex2d *)sceGuGetMemory(2 * sizeof(vertex2d));
sliceWidth = slice;
if (j + sliceWidth > width) sliceWidth = width - j;
points[0].u = sx + j;
points[0].v = sy;
points[0].x = dx + j;
points[0].y = dy;
points[0].z = 0;
points[0].color = 0;

points[1].u = sx + j + sliceWidth;
points[1].v = sy + height;
points[1].x = dx + j + sliceWidth;
points[1].y = dy + height;
points[1].z = 0;
points[1].color = 0;
sceGuDrawArray(GU_SPRITES, GU_COLOR_8888 | GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D, 2, 0, points);
}

// enable the depthtesting again.
sceGuEnable(GU_DEPTH_TEST);
sceGuDisable(GU_TEXTURE_2D);
}
void Image::render()
{
if(hidden || !(image != NULL && image->data != NULL))
return;
if(image->textureHeight >= 512 || image->textureWidth >= 512)
{
render_big();
return;
}
// we do not need to test for depth
sceGuDisable(GU_DEPTH_TEST);
sceGuEnable(GU_TEXTURE_2D);
if(image->palette != NULL)
{
if(image->palette->data != NULL)
{
// upload palette
sceGuClutMode(image->palette->pixelFormat,0,0xff,0);
sceGuClutLoad((image->palette->nentries>>3), image->palette->data);
}
}
// setting the texture
sceGuTexMode(image->pixelFormat,0,0,image->swizzled);
sceGuTexFilter( GU_LINEAR, GU_LINEAR );
sceGuTexFunc(GU_TFX_REPLACE, image->pixelFormat == GU_PSM_5650 ? GU_TCC_RGB : GU_TCC_RGBA);
sceGuTexImage(0, image->textureWidth, image->textureHeight, image->textureWidth, image->data);

vertex2d * points = (vertex2d *)sceGuGetMemory(4 * sizeof(vertex2d));
points[0].color = points[1].color = GU_RGBA(255,255,255,255);
points[2].color = points[3].color = GU_RGBA(255,255,255,255);

points[0].u = !mirroredVert ? 0.0f : image->textureWidth;
points[0].v = !mirroredHori ? 0.0f : image->textureHeight;
points[0].x = start.x;
points[0].y = start.y;
points[0].z = 0.0f;

points[1].u = !mirroredVert ? image->textureWidth : 0.0f;
points[1].v = !mirroredHori ? 0.0f : image->textureHeight;
points[1].x = end.x;
points[1].y = start.y;
points[1].z = 0.0f;

points[2].u = !mirroredVert ? 0.0f : image->textureWidth;
points[2].v = !mirroredHori ? image->textureHeight : 0.0f;
points[2].x = start.x;
points[2].y = end.y;
points[2].z = 0.0f;

points[3].u = !mirroredVert ? image->textureWidth : 0.0f;
points[3].v = !mirroredHori ? image->textureHeight : 0.0f;
points[3].x = end.x;
points[3].y = end.y;
points[3].z = 0.0f;

// draw the trianglestrip with transform 2D
sceGuDrawArray(GU_TRIANGLE_STRIP, GU_COLOR_8888 | GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D, 4, 0, points);

// enable the depthtesting again.
sceGuEnable(GU_DEPTH_TEST);
sceGuDisable(GU_TEXTURE_2D);

}


Share this post


Link to post
Share on other sites
Quote:
Original post by coolkehon
i tested my card and it says 2048 :( is there a workaround for this


Split your texture in multiple textures, but you really need textures that large?

Share this post


Link to post
Share on other sites
its for a game level that i do not tile :) and how can i edit the image pixels i still don't understand how that works

Share this post


Link to post
Share on other sites
glTexSubImage1D/2D/3D works in pretty much the same way as glTexImage1D/2D/3D except that you specify an x,y,width,height and you just update that rectangle with the data in the buffer you provide.

You could in theory keep a copy of the texture in RAM and when you modify the byte array (of the texture) just call a glTexSubImage1D/2D/3D for the whole texture and it'll update everything.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!