Войти
ПрограммированиеФорумГрафика

OpenGL и *.dds (2 стр)

Страницы: 1 2
#15
23:43, 10 июля 2006

Спасибо большое, разбираюсь

Прошло более 1 года
#16
9:32, 12 окт 2007

Актуально сейчас.
Напомню - в теме идёт речь о том, что в OpenGL при загрузке DDS надо флипать ее вертикально.

А если я пишу мультиапишный движок?

1) Неужели и правда в зависимости от формата изображения в коде менять текст. координаты?
2) Или на стадии создания художник должен вертеть IMAGE?
3) Или писать утилитку для экспорта в движок (которая тупо флипает картинку)?

Как правильно наладить взаимосвязь художников и программистов?
Кто как делает?

#17
9:36, 12 окт 2007

У меня есть интерфейс 3Д драйвера, так может в OpenGL реализации вообще везде текст. координаты по Y инвертить? Ведь в DX текст. корд. (0,0) начинается в левом верхнем углу?
Это вроде самый лучший вариант.

#18
13:38, 12 окт 2007

beetle2001
http://users.pandora.be/tfautre/softdev/ddsload/explanation.htm
Инфы немного, но разобраться можно. У меня получилось флипануть все варианты DDS, включая сжатые.

#19
13:34, 13 окт 2007

Сделал себе загрузку dds (кубемапы в том числе), за основу взял код из DevIL, никаких проблем не возникло.

Прошло более 2 лет
#20
13:12, 2 дек 2009

#include "loadDDS.h"
#include "Surface.h"
#include "SurfaceFormat.h"
#include <io/InputStream.h>
#include <io/OutputStream.h>
#include <pix/Image.h>
#include <pix/SurfaceFormat.h>
#include <lang/Debug.h>
#include <lang/Array.h>
#include <math.h>
#include <string.h>
#include <assert.h>
#include <algorithm>
#include "config.h"

//-----------------------------------------------------------------------------

using namespace io;
using namespace lang;

//-----------------------------------------------------------------------------

namespace pix
{
  /**
  * Computes pitch by DDS pixel format.
  * @return -1 if error.
  */
  static int getPitch( int width, SurfaceFormat format )
  {
    int pitch = -1;
    if ( format == SurfaceFormat::SURFACE_DXT1 )
      pitch = width * 2;
    else if ( format == SurfaceFormat::SURFACE_DXT3 || format == SurfaceFormat::SURFACE_DXT5 )
      pitch = width * 4;
    else if ( format.bltSupported() )
      pitch = width * format.pixelSize();
    else
      return -1;
   
    pitch = (pitch+3) & ~3;
    return pitch;
  }

  bool readSurfaceAndMipMaps( io::InputStream* file, int width, int height, int datasize, int cellsize, int mipmapcount, SurfaceFormat format, lang::Array<Surface>& surfaces )
  {
    int pitch = getPitch( width, format );
    if ( -1 == pitch )
      return false;
    surfaces.add( Surface( width, height, pitch, datasize, format ) );
    file->read( surfaces[surfaces.size()-1].data(), datasize );       

    int w = width;
    int h = height;
    for ( int i = 0; i < mipmapcount - 1; ++i )
    {
      w = w / 2 < 1 ? 1 : w / 2;
      h = h / 2 < 1 ? 1 : h / 2;

      int mmdatasize = -1;
      if ( format.compressed() )
      {
        mmdatasize = __max(1, w / 4) * __max(1, h / 4);
        mmdatasize *= cellsize;
      }
      else
      {
        mmdatasize = w*h*format.pixelSize();
      }

      int pitch = getPitch( w, format );
      if ( -1 == pitch )
        return false;

      surfaces.add( Surface( w, h, pitch, mmdatasize, format ) );
      file->read( surfaces[surfaces.size()-1].data(), mmdatasize );
    }

    return true;
  }


  bool loadDDS( io::InputStream* file, int* width, int* height, int* pitch, int* mipmaplevels, SurfaceFormat* format, Image::ImageType* type, lang::Array<Surface>& surfaces )
  {
    const char ddsMagic[] = "DDS ";   
    char magic[4];

    file->read( &magic, 4 );
   
    if ( memcmp( &magic, &ddsMagic, 4 ) != 0 )
    {
      Debug::printlnError( "loadDDS: magic incorrect" );
      return false;
    }
    char header[124];

    file->read( &header, 124 );

    // shortcut to parameters

    uint32_t* dwSize    = (uint32_t*)&header[0];
    uint32_t* dwFlags    = (uint32_t*)&header[4];
    uint32_t* dwHeight    = (uint32_t*)&header[8];
    uint32_t* dwWidth    = (uint32_t*)&header[12];
    uint32_t* dwPitchOrSize  = (uint32_t*)&header[16];
  //  uint32_t* dwDepth    = (uint32_t*)&header[20];  // Volume depth
    uint32_t* dwMipMapCount  = (uint32_t*)&header[24];
   
    char* ddPixelFormat    = &header[28 + 4*11];   
    uint32_t* pfSize    = (uint32_t*)ddPixelFormat;
    uint32_t* pfFlags    = (uint32_t*)&ddPixelFormat[4];
    char* pfFourCC      = &ddPixelFormat[8];
    uint32_t* pfRGBBitCount  = (uint32_t*)&ddPixelFormat[12];
    uint32_t* pfRBitMask  = (uint32_t*)&ddPixelFormat[16];
    uint32_t* pfGBitMask  = (uint32_t*)&ddPixelFormat[20];
    uint32_t* pfBBitMask  = (uint32_t*)&ddPixelFormat[24];
    uint32_t* pfAlphaBitMask= (uint32_t*)&ddPixelFormat[28];

    char* ddsCaps      = &header[28 + 4*11 + 32];
    uint32_t* dwCaps1    = (uint32_t*)ddsCaps;
    uint32_t* dwCaps2    = (uint32_t*)&ddsCaps[4];

    // translate image dimensions

    if ( *dwSize != 124 )
    {
      Debug::printlnError( "loadDDS: Invalid file" );
      return false;
    }

    // translate pixelformat

    if ( *pfSize != 32 )
    {
      Debug::printlnError( "loadDDS: Invalid file" );
      return false;
    }

    int datasize = 0;
    int mindatasize = 1;

    if ( *dwFlags & DDSD_WIDTH )
      *width = (int)*dwWidth;   
    if ( *dwFlags & DDSD_HEIGHT )
      *height = (int)*dwHeight;
    if ( *dwFlags & DDSD_PITCH )
    {
      *pitch = (int)*dwPitchOrSize;
      datasize = *pitch * *height;
    }
    else if ( *dwFlags & DDSD_LINEARSIZE )
      datasize = (int)*dwPitchOrSize;
    else
    {
      if ( *pfFlags & DDPF_FOURCC )
      {
        datasize = __max(1, *width / 4) * __max(1, *height / 4) * 8;
        if ( memcmp(pfFourCC, "DXT1", 4) != 0 )
          datasize *= 2;
      }
      else
      if ( ( *dwFlags & DDSD_WIDTH ) && ( *dwFlags & DDSD_HEIGHT ) && ( *dwFlags & DDSD_PIXELFORMAT ) )
        datasize = (int)*dwHeight * (int)*dwWidth * ( ((int)*pfRGBBitCount) >> 3 );
    }
    if ( *dwFlags & DDSD_MIPMAPCOUNT )
      *mipmaplevels = (int)*dwMipMapCount;


    if ( *pfFlags & DDPF_RGB )
    {
      if ( !(*pfFlags & DDPF_ALPHAPIXELS) )
        *pfAlphaBitMask = 0;
     
      SurfaceFormat fmt( *pfRGBBitCount, *pfRBitMask, *pfGBitMask, *pfBBitMask, *pfAlphaBitMask );
      if ( fmt.type() != SurfaceFormat::SURFACE_UNKNOWN )
        *format = fmt;
      else
      {
        Debug::printlnError( "loadDDS: Unsupported Pixelformat" );
        return false;
      }

      mindatasize = ((int)*pfRGBBitCount) >> 3;
    }
    else if ( *pfFlags & DDPF_FOURCC )
    {
      if (memcmp(pfFourCC, "DXT1", 4) == 0 )
      {
        *format = SurfaceFormat( SurfaceFormat::SURFACE_DXT1 );
        *pitch = *width * 2;
        mindatasize = 8;
      }
      else if (memcmp(pfFourCC, "DXT3", 4) == 0 )
      {
        *format = SurfaceFormat( SurfaceFormat::SURFACE_DXT3 );
        *pitch = *width * 4;
        mindatasize = 16;
      }
      else if (memcmp(pfFourCC, "DXT5", 4) == 0 )
      {
        *format = SurfaceFormat( SurfaceFormat::SURFACE_DXT5 );
        *pitch = *width * 4;
        mindatasize = 16;
      }
      else
      {
        Debug::printlnError( "loadDDS: Unsupported Pixelformat" );
        return false;
      }
    } 

    if ( datasize == 0 )
    {
      Debug::printlnError( "loadDDS: Invalid file" );
      return false;
    }

    bool ok = false;
    if ( *dwCaps2 & DDSCAPS2_CUBEMAP )
    {
      if ( *dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEX )
        ok = readSurfaceAndMipMaps( file, *width, *height, datasize, mindatasize, (int)*dwMipMapCount, *format, surfaces );

      if ( *dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEX )
        ok = readSurfaceAndMipMaps( file, *width, *height, datasize, mindatasize, (int)*dwMipMapCount, *format, surfaces );

      if ( *dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEY )
        ok = readSurfaceAndMipMaps( file, *width, *height, datasize, mindatasize, (int)*dwMipMapCount, *format, surfaces );

      if ( *dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEY )
        ok = readSurfaceAndMipMaps( file, *width, *height, datasize, mindatasize, (int)*dwMipMapCount, *format, surfaces );

      if ( *dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEZ )
        ok = readSurfaceAndMipMaps( file, *width, *height, datasize, mindatasize, (int)*dwMipMapCount, *format, surfaces );

      if ( *dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ )
        ok = readSurfaceAndMipMaps( file, *width, *height, datasize, mindatasize, (int)*dwMipMapCount, *format, surfaces );
    }
    else
    {
      ok = readSurfaceAndMipMaps( file, *width, *height, datasize, mindatasize, (int)*dwMipMapCount, *format, surfaces );
    }
    // find image type and return

    if ( ok )
    {
      if (*dwCaps2 & DDSCAPS2_CUBEMAP)
        *type = Image::TYPE_CUBEMAP;
      else if (*dwCaps1 & DDSCAPS_TEXTURE)
        *type = Image::TYPE_BITMAP;
      else
        *type = Image::TYPE_CUSTOM;
    }

    return ok;
  }


} // pix

#21
13:13, 2 дек 2009

#include <stdio.h>
#include <stdint.h>
#include <lang/Array.h>
#include <pix/Image.h>
#include <pix/Surface.h>


namespace io {
  class OutputStream;
  class InputStream;}


namespace pix
{


class SurfaceFormat;

enum DDS_Flags {
  DDSD_CAPS      = 0x00000001,
  DDSD_HEIGHT      = 0x00000002,
  DDSD_WIDTH      = 0x00000004,
  DDSD_PITCH      = 0x00000008,
  DDSD_PIXELFORMAT  = 0x00001000,
  DDSD_MIPMAPCOUNT  = 0x00020000,
  DDSD_LINEARSIZE    = 0x00080000,
  DDSD_DEPTH      = 0x00800000,
};

enum DDS_PixelFormat_Flags {
  DDPF_ALPHAPIXELS  = 0x00000001,
  DDPF_FOURCC      = 0x00000004,
  DDPF_RGB      = 0x00000040,
};

enum DDS_dwCaps1 {
  DDSCAPS_COMPLEX    = 0x00000008,
  DDSCAPS_TEXTURE    = 0x00001000,
  DDSCAPS_MIPMAP    = 0x00400000,
};

enum DDS_dwCaps2 {
  DDSCAPS2_CUBEMAP      = 0x00000200,
  DDSCAPS2_CUBEMAP_POSITIVEX  = 0x00000400,
  DDSCAPS2_CUBEMAP_NEGATIVEX  = 0x00000800,
  DDSCAPS2_CUBEMAP_POSITIVEY  = 0x00001000,
  DDSCAPS2_CUBEMAP_NEGATIVEY  = 0x00002000,
  DDSCAPS2_CUBEMAP_POSITIVEZ  = 0x00004000,
  DDSCAPS2_CUBEMAP_NEGATIVEZ  = 0x00008000,
  DDSCAPS2_VOLUME        = 0x00200000,
};

// Why surfaces and directly and not pointers? DDS files can contain a variable amount of bitmaps (including mipmaps) and also contain header data which will be used by the driver

/**
* Loads DDS image from the file.
* @return true if load ok. */
bool loadDDS( io::InputStream* file, int* width, int* height, int* pitch, int* mipMapLevels, SurfaceFormat* format, Image::ImageType* type, lang::Array<Surface>& surfaces );


}

Прошло более 8 лет
#22
10:39, 15 июня 2018

dds хороший формат для разработки игры?

#23
12:18, 15 июня 2018

admirall_btr
Я делаю гораздо проще = при конвертации моделей инвертирую координату V, всё равно приходится поворачивать координаты YZ.
При этом и текстуры остаются нормальными, и в самом движке ничего не делается.

> dds хороший формат для разработки игры?
Для OpenGL KTX гораздо проще, а форматы сжатия те же.

#24
16:10, 15 июня 2018

Никак не могу подобрать лопату: серебряную или золотую?

#25
18:14, 15 июня 2018

платиновую, ибо человек 9 лет думал, а тот ли он формат использует, и вот, наконец, решил спросить об этом

#26
22:05, 15 июня 2018

PA3UJIb

Вообще-то выбор формата текстур - это очень важное архитектурное решение, один раз неправильно выбрал и 9 лет работы в помойку. Так что лучше все таки основательно подумать.

#27
23:37, 15 июня 2018

bool
Лолшто. Если из-за смены формата 9 лет работы становятся бесполезными - то им изначально только в помойке место и было.

#28
2:10, 16 июня 2018

Delfigamer
я поднимал табличку "сарказм", но, возможно, она была в другом формате, не очень понятном тебе. Для другого апи, скорее всего.

Страницы: 1 2
ПрограммированиеФорумГрафика

Тема в архиве.