суббота, 5 ноября 2011 г.

Texture vs Bitmap

Намучавшись с выводом фона, я решил что уж корабль нарисую без проблем. По сути почти тоже самое - загрузить картинку и нарисовать ее в заданных координатах, попутно повернув на нужный угол. Однако жизнь полна сюрпризов - поворот изображения выводимого glDrawPixels - не предусмотрен. Т.е. сделать это конечно можно, но через такую же задницу, как и загрузка - т.е лучше этого не делать. Так что пришлось наконец взяться за текстуры. 

 

И тут выяснилось, что все мои танцы с бубном вокруг glDrawPixels - идиотизм чистой воды. То же самое делается через текстуры НАМНОГО проще. Видимо потому что текстуры - мэйнстрим, а вывод пикселей - рудиментарный придаток. Итак, сравните два куска кода. Первый загружает графический файл и переводит его в подходящую для использования в glDrawPixels форму:


image = ImageIO.read(new File(fname));

imgHeight = image.getHeight(null);
imgWidth = image.getWidth(null);
WritableRaster raster =
Raster.createInterleavedRaster( DataBuffer.TYPE_BYTE,
imgWidth,
imgHeight,
4,
null );

ColorModel colorModel =
new ComponentColorModel( ColorSpace.getInstance(ColorSpace.CS_sRGB ),//CS_sRGB
new int[] {8,8,8,8},
true,
false,
ComponentColorModel.TRANSLUCENT,//,
DataBuffer.TYPE_BYTE );
bufImg = new BufferedImage (colorModel, // color model
raster,
false, // isRasterPremultiplied
null); // properties

g = bufImg.createGraphics();
AffineTransform gt = new AffineTransform();
gt.translate (0, imgHeight);
gt.scale (1, -1d);
g.transform ( gt );
g.drawImage ( image, null, null );
raster=bufImg.getRaster();//!!
DataBufferByte imgBuf = (DataBufferByte)raster.getDataBuffer();
imgRGBA=ByteBuffer.wrap(imgBuf.getData());
g.dispose();

после чего картинка выводится следующим образом


gl.glRasterPos2d(x,y);
gl.glDrawPixels(imgWidth, imgHeight, GL2.GL_RGBA, GL2.GL_UNSIGNED_BYTE,imgRGBA);

А вот вариант с текстурой. Загрузка:


texture = TextureIO.newTexture(new File(fname), false);
h = texture.getHeight();
w = texture.getWidth();

Рисование, причем уже сразу с поворотом:


gl.glTranslated(x,y,0);
gl.glRotated(angle, 0, 0, 1);
gl.glEnable(GL2.GL_TEXTURE_2D);
gl.glTexEnvf(GL2.GL_TEXTURE_ENV,GL2.GL_TEXTURE_ENV_MODE,GL2.GL_REPLACE);
texture.bind(gl);

gl.glBegin(GL2.GL_QUADS);
gl.glTexCoord2d(0.0,1.0); gl.glVertex2d(-design.w/2,-design.h/2);
gl.glTexCoord2d(0.0,0.0); gl.glVertex2d(-design.w/2,design.h/2);
gl.glTexCoord2d(1.0,0.0); gl.glVertex2d(design.w/2,design.h/2);
gl.glTexCoord2d(1.0,1.0); gl.glVertex2d(design.w/2,-design.h/2);
gl.glEnd();
gl.glDisable(GL2.GL_TEXTURE_2D);

Кажется что во втором варианте немного сложнее вывод на экран - но это только кажется. Работают традиционные способы масштабирования, переноса и поворота - в то время как при первом варианте все это реализуется намного медленнее, сложнее и отнюдь не очевидными способами.

Update: не сразу заметил что изображение выводится вверх ногами. Пришлось его перевернуть прямо при рисовании. Здесь код уже поправил. Можно заметить что координаты вершин идут по часовой стрелке, а координаты текстуры против. И начинается отрисовка вершин с левой-нижней, а текстура - с левой-верхней точек.

Комментариев нет:

Отправить комментарий