分离VKDebugOut以及VKProperties

This commit is contained in:
hyzboy 2019-11-06 20:52:09 +08:00
parent dbfa2ec526
commit 19be1c4d9f
21 changed files with 1788 additions and 241 deletions

View File

@ -52,6 +52,8 @@ int main(int,char **)
InitNativeWindowSystem();
InitVulkanProperties();
win=CreateRenderWindow(OS_TEXT("VulkanTest"));
if(!win)
return(false);

196
inc/hgl/graph/Spline.cpp Normal file
View File

@ -0,0 +1,196 @@
#include <cassert>
#include <algorithm>
namespace hgl
{
namespace graph
{
template<typename Point_t, typename Real_t>
Spline<Point_t, Real_t>::Spline(
int k,
SplineNode node_type)
:
_node_type(node_type),
_k(k),
_point( _k ),
_vec( _k-1 ),
_node( _k + _point.size() )
{
assert_splines();
}
// -----------------------------------------------------------------------------
template<typename Point_t, typename Real_t>
void Spline<Point_t, Real_t>::set_ctrl_points(const std::vector<Point_t>& point)
{
_point = point;
_vec.resize(_point.size() - 1);
for(int i = 0; i < (int)_vec.size(); ++i)
_vec[i] = _point[i + 1] - _point[i];
set_nodal_vector();
assert_splines();
for(int i = 0; i < (int)_vec.size(); ++i)
_vec[i] /= _node[_k+i] - _node[i+1];
}
// -----------------------------------------------------------------------------
template<typename Point_t, typename Real_t>
void Spline<Point_t, Real_t>::get_ctrl_points(std::vector<Point_t>& points) const
{
points = _point;
}
// -----------------------------------------------------------------------------
/// The the nodal vector type
template<typename Point_t, typename Real_t>
void Spline<Point_t, Real_t>::set_node_type( SplineNode type)
{
_node_type = type;
set_nodal_vector();
assert_splines();
}
// -----------------------------------------------------------------------------
template<typename Point_t, typename Real_t>
Point_t Spline<Point_t, Real_t>::eval_f(Real_t u) const
{
u = std::max(std::min(u, (Real_t)1), (Real_t)0); // clamp between [0 1]
return eval(u, _point, _k, _node);
}
// -----------------------------------------------------------------------------
template<typename Point_t, typename Real_t>
Point_t Spline<Point_t, Real_t>::eval_df(Real_t u) const
{
u = std::max(std::min(u, (Real_t)1), (Real_t)0); // clamp between [0 1]
return eval(u, _vec, (_k-1), _node, 1) * (Real_t)(_k-1);
}
// -----------------------------------------------------------------------------
template<typename Point_t, typename Real_t>
void Spline<Point_t, Real_t>::assert_splines() const
{
assert( _k > 1);
assert((int)_point.size() >= _k );
assert(_node. size() == (_k + _point.size()) );
assert(_point.size() == (_vec.size() + 1) );
}
// -----------------------------------------------------------------------------
template<typename Point_t, typename Real_t>
void Spline<Point_t, Real_t>::set_nodal_vector()
{
if( _node_type == SplineNode::OPEN_UNIFORM)
set_node_to_open_uniform();
else if( _node_type == spline::eUNIFORM )
set_node_to_uniform();
}
// -----------------------------------------------------------------------------
template<typename Point_t, typename Real_t>
void Spline<Point_t, Real_t>::set_node_to_uniform()
{
const int n = _point.size() - 1;
_node.resize( _k + n + 1 );
Real_t step = (Real_t)1 / (Real_t)(n-_k+2);
for (int i = 0; i < (int)_node.size(); ++i){
_node[i] = ((Real_t)i) * step - step * (Real_t)(_k-1);
}
}
// -----------------------------------------------------------------------------
template<typename Point_t, typename Real_t>
void Spline<Point_t, Real_t>::set_node_to_open_uniform()
{
_node.resize( _k + _point.size() );
int acc = 1;
for (int i = 0; i < (int)_node.size(); ++i)
{
if(i < _k)
_node[i] = 0.;
else if( i >= ((int)_point.size() + 1) )
_node[i] = 1.;
else{
_node[i] = (Real_t)acc / (Real_t)(_point.size() + 1 - _k);
acc++;
}
}
}
// -----------------------------------------------------------------------------
template<typename Point_t, typename Real_t>
Point_t Spline<Point_t, Real_t>::
eval(Real_t u,
const std::vector<Point_t>& point,
int k,
const std::vector<Real_t>& node,
int off) const
{
assert( k > 1);
assert((int)point.size() >= k );
assert_splines();
int dec = 0;
// TODO: better search with dychotomi ?
// TODO: check for overflow
while( u > node[dec + k + off] )
dec++;
// TODO: use buffers in attributes for better performances ?
std::vector<Point_t> p_rec(k, Point_t());
for(int i = dec, j = 0; i < (dec + k); ++i, ++j)
p_rec[j] = point[i];
std::vector<Real_t> node_rec(k + k - 2, (Real_t)0);
for(int i = (dec + 1), j = 0; i < (dec + k + k - 1); ++i, ++j)
node_rec[j] = node[i + off];
return eval_rec(u, p_rec, k, node_rec);
}
// -----------------------------------------------------------------------------
template<typename Point_t, typename Real_t>
Point_t Spline<Point_t, Real_t>::
eval_rec(Real_t u,
std::vector<Point_t> p_in,
int k,
std::vector<Real_t> node_in) const
{
if(p_in.size() == 1)
return p_in[0];
// TODO: use buffers in attributes for better performances ?
std::vector<Point_t> p_out(k - 1, Point_t());
for(int i = 0; i < (k - 1); ++i)
{
const Real_t n0 = node_in[i + k - 1];
const Real_t n1 = node_in[i];
const Real_t f0 = (n0 - u) / (n0 - n1);
const Real_t f1 = (u - n1) / (n0 - n1);
p_out[i] = p_in[i] * f0 + p_in[i + 1] * f1;
}
std::vector<Real_t> node_out(node_in.size() - 2);
for(int i = 1, j = 0; i < ((int)node_in.size()-1); ++i, ++j)
node_out[j] = node_in[i];
return eval_rec(u, p_out, (k - 1), node_out);
}
}//namespace graph
}//namespace hgl

100
inc/hgl/graph/Spline.h Normal file
View File

@ -0,0 +1,100 @@
#ifndef HGL_GRAPH_SPLINE_INCLUDE
#define HGL_GRAPH_SPLINE_INCLUDE
#include<hgl/math/Vector.h>
#include<vector>
namespace hgl
{
namespace graph
{
enum class SplineNode
{
UNIFORM,
OPEN_UNIFORM ///< Connected to the first and last control points
};
template<typename Point_t, typename Real_t> class Spline
{
public:
/// Type of the nodal vector
/// @param k : order of the spline (minimum is two)
/// @param node_type : nodal vector type (uniform, open_uniform)
/// This will define the behavior of the spline with its control points
/// as well as its speed according to its parameter.
Spline(int k = 2, SplineNode node_type = SplineNode::OPEN_UNIFORM);
/// Set the position of the spline control points.
void set_ctrl_points(const std::vector<Point_t>& point);
/// Get the control points of the spline
void get_ctrl_points(std::vector<Point_t>& points) const;
/// The the nodal vector type
void set_node_type( SplineNode type);
/// Evaluate position of the spline
/// @param u : curve parameter ranging from [0; 1]
Point_t eval_f(Real_t u) const;
/// Evaluate speed of the spline
Point_t eval_df(Real_t u) const;
int get_order() const { return _k; }
private:
// -------------------------------------------------------------------------
/// @name Class tools
// -------------------------------------------------------------------------
void assert_splines() const;
/// set value and size of the nodal vector depending on the current number
/// of control points
void set_nodal_vector();
/// Set values of the nodal vector to be uniform
void set_node_to_uniform();
/// Set values of the nodal vector to be open uniform
void set_node_to_open_uniform();
/// Evaluate the equation of a splines using the blossom algorithm
/// @param u : the curve parameter which range from the values
/// [node[k-1]; node[point.size()]]
/// @param point : the control points which size must be at least equal to
/// the order of the spline (point.size() >= k)
/// @param k : the spline order (degree == k-1)
/// @param node : the nodal vector which defines the speed of the spline
/// parameter u. The nodal vector size must be equal to (k + point.size())
/// @param off : offset to apply to the nodal vector 'node' before reading
/// from it. this is useful to compute derivatives.
Point_t eval(Real_t u,
const std::vector<Point_t>& point,
int k,
const std::vector<Real_t>& node,
int off = 0) const;
Point_t eval_rec(Real_t u,
std::vector<Point_t> p_in,
int k,
std::vector<Real_t> node_in) const;
// -------------------------------------------------------------------------
/// @name attributes
// -------------------------------------------------------------------------
SplineNode _node_type; ///< Nodal vector type
int _k; ///< spline order
std::vector<Point_t> _point; ///< Control points
std::vector<Point_t> _vec; ///< Control points differences
std::vector<Real_t> _node; ///< Nodal vector
};//class Spline
using Spline2f=Spline<Vector2f,float>;
using Spline3f=Spline<Vector3f,float>;
}//namespace graph
}//namespace hgl
#include<hgl/graph/Spline.cpp>
#endif//HGL_GRAPH_SPLINE_INCLUDE

103
inc/hgl/graph/TileData.h Normal file
View File

@ -0,0 +1,103 @@
#ifndef HGL_GRAPH_TILE_DATA_INCLUDE
#define HGL_GRAPH_TILE_DATA_INCLUDE
#include<hgl/graph/TextureFormat.h>
namespace hgl
{
namespace graph
{
class Texture2D;
class Renderable;
class Bitmap2D;
/**
* TileData是一种处理将大量等同贴图的管理机制(:Tile的宽高不必是2的幂)<br>
* Tile的增加删除
*/
class TileData ///Tile数据管理
{
public:
struct Object ///Tile对象
{
int index;
double fl,ft;
double fw,fh;
int width,height;
};
protected:
Texture2D *tile_texture; ///<Tile所用贴图
TileData::Object **tile_object; ///<所有Tile对象指针
int tile_width,tile_height; ///<tile的宽和高
int tile_count,tile_total; ///<当前tile数量与最大数量
int tile_rows,tile_cols; ///<贴图中可用的tile行数和列数
protected:
int FindSpace(); ///<寻找一个空位
void WriteTile(int,TileData::Object *,void *,unsigned int,TextureSourceFormat,int,int); ///<写入一个Tile
public:
int GetWidth ()const{return tile_width;} ///<取得Tile宽
int GetHeight ()const{return tile_height;} ///<取得Tile高
int GetCount ()const{return tile_count;} ///<取得Tile数量
int GetMaxCount ()const{return tile_total;} ///<取得Tile最大数量
int GetFreeCount()const{return tile_total-tile_count;} ///<取得空余Tile数量
Texture2D * GetTexture ()const{return tile_texture;} ///<取得贴图
public:
TileData(int,int,int, TextureSourceFormat);
virtual ~TileData();
TileData::Object *Add(void *,unsigned int,TextureSourceFormat,int=-1,int=-1); ///<增加一个Tile
bool Delete(TileData::Object *); ///<删除一个Tile
bool Change(TileData::Object *,void *,unsigned int,TextureSourceFormat,int=-1,int=-1); ///<更改一个Tile的数据内容
void Clear(); ///<清除Tile数据
};//class TileData
template<typename T> class VertexBuffer2;
/**
* Tile为一个2D矩形数据到顶点缓冲区上
* @param obj Tile对象
* @param vertex 2d顶点坐标缓冲区
* @param tex_coord
* @param left
* @param top
* @param scale_width
* @param scale_height
*/
template<typename T1,typename T2>
__inline void RenderToVB2DRect( VertexBuffer2<T1> *vertex,
VertexBuffer2<T2> *tex_coord,
const TileData::Object *obj,
const float left,
const float top,
const float scale_width=1.0f,
const float scale_height=1.0f)
{
if(!obj||!vertex||!tex_coord)return;
tex_coord->WriteRect( obj->fl,
obj->ft,
obj->fw,
obj->fh);
vertex->WriteRect( left,
top,
scale_width*float(obj->width),
scale_height*float(obj->height));
}
}//namespace graph
}//namespace hgl
#endif//HGL_GRAPH_TILE_DATA_INCLUDE

View File

@ -0,0 +1,25 @@
static FontInfo *DefaultFont;
private:
UTF16String name;
int width,height;
bool bold,italic;
protected:
UTF16String &GetName(){return name;}
void SetName(UTF16String &);
int GetWidth(){return width;}
int GetHeight(){return height;}
bool GetBold(){return bold;}
bool GetItalic(){return italic;}
void SetWidth(int);
void SetHeight(int);
void SetBold(bool);
void SetItalic(bool);
void InitPrivate();

View File

@ -0,0 +1,51 @@
#ifndef HGL_FONT_INFO_INCLUDE
#define HGL_FONT_INFO_INCLUDE
#include<hgl/type/DataType.h>
#include<hgl/type/Color4f.h>
#include<hgl/type/BaseString.h>
namespace hgl
{
/**
* <br>
* 线
*/
class FontInfo ///字体数据结构
{
#include<hgl/graph/FontInfo.Attrib.h>
public: //属性
Property<UTF16String> Name; ///<字体名称
Property<int> Width; ///<平均字体宽度
Property<int> Height; ///<字体高度
Property<bool> Bold; ///<是否粗体
Property<bool> Italic; ///<是否斜体
public: //事件
DefEvent(void,OnChange,(FontInfo *)); ///<字体改变事件
public: //方法
FontInfo();
FontInfo(const FontInfo &);
FontInfo(const UTF16String &,int,int,bool=false,bool=false);
static void SetDefaultFont(const UTF16String &,int,int,bool,bool); ///<设置缺省字体
static void SetDefaultFont(const FontInfo &); ///<设置缺省字体
static void ClearDefaultFont(); ///<清除缺省字体
void Set(const UTF16String &,int,int,bool=false,bool=false); ///<设置字体
public: //操作符重载
bool operator == (const FontInfo &);
bool operator != (const FontInfo &);
void operator = (const FontInfo &);
};//class FontInfo
}//namespace hgl
#endif//HGL_FONT_INFO_INCLUDE

View File

@ -0,0 +1,50 @@
#ifndef HGL_GRAPH_FONT_SOURCE_INCLUDE
#define HGL_GRAPH_FONT_SOURCE_INCLUDE
#include<hgl/graph/FontInfo.h>
namespace hgl
{
namespace graph
{
/**
* <br>
*
*/
class FontSource
{
public:
/**
*
*/
struct Bitmap
{
int x,y; //图像显示偏移
int w,h; //图像尺寸
int adv_x,adv_y;//字符尺寸
unsigned char *data;
};//struct Bitmap
protected:
FontInfo fnt;
FontSource::Bitmap char_bitmap[0xFFFF]; ///<字符位图数据
protected:
virtual bool MakeCharBitmap(u16char)=0; ///<产生字体数据
virtual int GetLineHeight()const=0; ///<取得行高
public:
FontSource(const FontInfo &);
virtual ~FontSource();
FontSource::Bitmap *GetCharBitmap(u16char); ///<取得字体数据
};//class FontSource
}//namespace graph
}//namespace hgl
#endif//HGL_GRAPH_FONT_SOURCE_INCLUDE

View File

@ -0,0 +1,175 @@
#ifndef HGL_GRAPH_TILE_FONT_INCLUDE
#define HGL_GRAPH_TILE_FONT_INCLUDE
#include<hgl/algorithm/VectorMath.h>
#include<hgl/type/Color4f.h>
#include<hgl/type/ActiveChain.h>
#include<hgl/graph/TileData.h>
#include<hgl/graph/FontSource.h>
#include<hgl/graph/Makeup.h>
#include<hgl/graph/VertexBuffer.h>
namespace hgl
{
namespace graph
{
struct FontInfo;
class Renderable;
class Material;
/**
* 使Tile代表一个字符的管理模块<br>
* 使使
*/
class TileFont ///Tile字体
{
protected:
TileData *tile_data; ///<Tile管理器
FontSource *chs_source,*eng_source; ///<字体数据源
ActiveChain<u16char,TileData::Object *> fud; ///<字体缓冲管理
uint8 *char_bitmap_buffer; ///<字符位图缓冲区
uint char_bitmap_bytes; ///<字符位图字节数
VB2f *vertex2d; ///<绘制用顶点坐标
VB2f *tex_coord; ///<绘制用顶点坐标
// VB1ui *vertex_color; ///<绘制用顶点色
Material *fnt_mtl; ///<绘制用材质
Renderable *fnt_draw; ///<绘制用对象
int tile_width,tile_height; ///<所使用的Tile宽高
int font_height;
int line_distance;
protected:
void Clear(const u16char &,TileData::Object *&); ///<清除某个字
FontSource::Bitmap *GetCharBitmap(const u16char &ch) ///<取得字符位图数据
{return ((ch<=0xFF?eng_source:chs_source)->GetCharBitmap(ch));}
FontSource::Bitmap *MakeCharBitmap(const u16char &ch); ///<生成字符位图数据
TileData::Object *GetCharData(const u16char &); ///<取得字符数据
bool MakeupText(Makeup &,int,int,const u16char *,int); ///<排版字符串
public:
int GetHeight ()const {return font_height;} ///<取得字符高度
int GetLineDistance ()const {return line_distance;} ///<取得行间距
void SetLineDistance(int n) {line_distance=n;}
public: //属性
Color4f Color; ///<颜色
public:
TileFont(int,TileData *,FontSource *,FontSource *);
virtual ~TileFont();
float CharWidth(u16char); ///<指定字符宽度
float GetStringWidth(const u16char *,int=-1); ///<求字符串宽度
public:
bool MakeupText(Makeup &,const u16char *,int=-1); ///<排版字符串
bool MakeupText(Makeup &,const u16char *,int,TextAlignment); ///<排版字符串
void Draw(const Matrix4f *,const Makeup &,int=-1); ///<根据排版进行绘制
void Draw(float l,float t,const Makeup &makeup,int limit_char=-1) ///<根据排版进行绘制
{
const Matrix4f mat=translate(l,t,0);
Draw(&mat,makeup,limit_char);
}
/**
* ,,\n
* @param mat modelview变换矩阵
* @param str
* @param limit_char ,-1
* @return
* @return <0
*/
float DrawString(const Matrix4f *mat,const u16char *str,int limit_char=-1) ///<绘制一个字符串,可限制字数,并且处理\n
{
Makeup m;
if(!MakeupText(m,str,limit_char))
return(-1);
Draw(mat,m,limit_char);
return m.Width;
}
/**
* ,,\n
* @param x X坐标
* @param y Y坐标
* @param str
* @param limit_char ,-1
* @return
* @return <0
*/
float DrawString(float x,float y,const u16char *str,int limit_char=-1) ///<绘制一个字符串,可限制字数,并且处理\n
{
const Matrix4f mat=translate(x,y,0);
return DrawString(&mat,str,limit_char);
}
float DrawFormat(const Matrix4f *mat,const u16char *,...); ///<绘制一个格式化的字符串
float DrawFormat(float,float,const u16char *,...); ///<绘制一个格式化的字符串
};//class TileFont
TileFont *CreateTileFont(const FontInfo &,const FontInfo &,int=-1); ///<创建一个字体,使用系统字体
/**
* Tile字体
* @param chs_fontname
* @param eng_fontname
* @param width ,0,
* @param height
* @param bold ,false
* @param italic ,false
* @param anti 齿,true
* @param count
*/
TileFont *CreateTileFont(const u16char *chs_fontname,const u16char *eng_fontname,int width,int height,bool bold=false,bool italic=false,bool anti=true,int count=-1);
/**
* Tile字体,
* @param fontname
* @param width ,0,
* @param height
* @param bold ,false
* @param italic ,false
* @param anti 齿,true
* @param count
*/
__inline TileFont *CreateTileFont(const u16char *fontname,int width,int height,bool bold=false,bool italic=false,bool anti=true,int count=-1)
{
return CreateTileFont(fontname,fontname,width,height,bold,italic,anti,count);
}
/**
* Tile字体,
* @param chs_fontname
* @param eng_fontname
* @param width ,0,
* @param height
* @param count
*/
__inline TileFont *CreateTileFont(const u16char *chs_fontname,const u16char *eng_fontname,int width,int height,int count=-1)
{
return CreateTileFont(chs_fontname,eng_fontname,width,height,false,false,true,count);
}
}//namespace graph
}//namespace hgl
#endif//HGL_GRAPH_TILE_FONT_INCLUDE

View File

@ -104,5 +104,11 @@ inline void debug_out(const hgl::List<VkExtensionProperties> &extension_properti
++ep;
}
}
void InitVulkanProperties();
const List<VkLayerProperties> & GetLayerProperties();
const List<VkExtensionProperties> & GetExtensionProperties();
const bool CheckLayerSupport(const char *);
VK_NAMESPACE_END
#endif//HGL_GRAPH_VULKAN_INCLUDE

View File

@ -0,0 +1,23 @@
#ifndef HGL_GRAPH_VULKAN_DEBUG_OUT_INCLUDE
#define HGL_GRAPH_VULKAN_DEBUG_OUT_INCLUDE
#include<hgl/graph/vulkan/VK.h>
VK_NAMESPACE_BEGIN
class VKDebugOut
{
VkInstance inst=nullptr;
VkDebugUtilsMessengerEXT debug_messenger;
VkDebugReportCallbackEXT debug_report_callback;
public:
VKDebugOut();
virtual ~VKDebugOut();
virtual bool Init(VkInstance);
};//class VKDebugOut
VK_NAMESPACE_END
#endif//HGL_GRAPH_VULKAN_DEBUG_OUT_INCLUDE

View File

@ -5,17 +5,14 @@
#include<hgl/type/List.h>
#include<hgl/platform/Window.h>
#include<hgl/graph/vulkan/VKPhysicalDevice.h>
#include<hgl/graph/vulkan/VKDebugOut.h>
VK_NAMESPACE_BEGIN
class Instance
{
VkInstance inst;
List<VkLayerProperties> layer_properties;
List<VkExtensionProperties> extension_properties;
VkDebugUtilsMessengerEXT debug_messenger;
VkDebugReportCallbackEXT debug_report_callback;
VKDebugOut *debug_out;
CharPointerList ext_list;
@ -23,9 +20,9 @@ VK_NAMESPACE_BEGIN
private:
friend Instance *CreateInstance(const UTF8String &app_name);
friend Instance *CreateInstance(const UTF8String &app_name,VKDebugOut *do=nullptr);
Instance(VkInstance,CharPointerList &);
Instance(VkInstance,VKDebugOut *,CharPointerList &);
public:
@ -33,13 +30,11 @@ VK_NAMESPACE_BEGIN
operator VkInstance (){return inst;}
const List<VkLayerProperties> & GetLayerProperties ()const {return layer_properties;}
const bool CheckLayerSupport (const UTF8String &)const;
const CharPointerList & GetExtList ()const {return ext_list;}
const ObjectList<PhysicalDevice> &GetDeviceList ()const {return physical_devices;}
const PhysicalDevice * GetDevice (VkPhysicalDeviceType)const;
};//class Instance
Instance *CreateInstance(const UTF8String &); ///<创建一个Vulkan实例
Instance *CreateInstance(const UTF8String &,VKDebugOut *do=nullptr); ///<创建一个Vulkan实例
VK_NAMESPACE_END
#endif//HGL_GRAPH_VULKAN_INSTANCE_INCLUDE

68
inc/hgl/input/Event.h Normal file
View File

@ -0,0 +1,68 @@
#pragma once
#include<hgl/type/DataType.h>
namespace hgl
{
namespace device_input
{
#pragma pack(push,1)
union InputEvent
{
struct
{
uint8 key;
}key_push;
struct
{
uint8 key;
}key_pop;
struct
{
uint16 x, y;
}mouse_move;
struct
{
uint8 key;
}mouse_key_push;
struct
{
uint8 key;
}mouse_key_pop;
struct
{
int16 x, y;
}mouse_wheel;
struct
{
int8 x, y;
}joystick_axis;
struct
{
uint8 key;
}joystick_key_push;
struct
{
uint8 key;
}joystick_key_pop;
struct
{
uint16 x, y;
uint16 power;
}wacom;
struct
{
u16char ch;
}char_input;
};//union InputEvent
#pragma pack(pop)
}//namespace device_input
}//namespace hgl

15
res/shader/test.geom Normal file
View File

@ -0,0 +1,15 @@
#version 450 core
layout(binding = 0) uniform WorldMatrix
{
mat4 two_dim;
mat4 projection;
mat4 modelview;
mat4 mvp;
mat3 normal;
} world;
void main()
{
gl_Position=vec4(1.0)*world.mvp;
}

View File

@ -2,6 +2,7 @@
SET(RENDER_DEVICE_VULKAN_SOURCE VKFormat.cpp
VKMemory.cpp
VKProperties.cpp
VKInstance.cpp
VKPhysicalDevice.cpp
VKImageView.cpp

View File

@ -0,0 +1,171 @@
#include<hgl/graph/vulkan/VK.h>
#include<iostream>
VK_NAMESPACE_BEGIN
namespace
{
VkResult CreateDebugUtilsMessengerEXT(VkInstance instance,const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,const VkAllocationCallbacks *pAllocator,VkDebugUtilsMessengerEXT *pDebugMessenger)
{
auto func=(PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance,"vkCreateDebugUtilsMessengerEXT");
if(func)
{
return func(instance,pCreateInfo,pAllocator,pDebugMessenger);
}
else
{
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
}
void DestroyDebugUtilsMessengerEXT(VkInstance instance,VkDebugUtilsMessengerEXT debugMessenger,const VkAllocationCallbacks *pAllocator)
{
auto func=(PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance,"vkDestroyDebugUtilsMessengerEXT");
if(func)
{
func(instance,debugMessenger,pAllocator);
}
}
VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,VkDebugUtilsMessageTypeFlagsEXT messageType,const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,void *pUserData)
{
if(messageSeverity&VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
{
std::cout<<"ERROR: "<<pCallbackData->pMessage<<std::endl;
}
else
if(messageSeverity&VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
{
std::cout<<"WARNING: "<<pCallbackData->pMessage<<std::endl;
}
else
if(messageSeverity&VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT)
{
std::cout<<"INFO: "<<pCallbackData->pMessage<<std::endl;
}
else
if(messageSeverity&VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT)
{
std::cout<<"VERBOSE: "<<pCallbackData->pMessage<<std::endl;
}
else
std::cerr<<"validation layer: "<<pCallbackData->pMessage<<std::endl;
return VK_FALSE;
}
bool CreateDebugReportCallbackEXT(VkInstance instance,const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,const VkAllocationCallbacks *pAllocator,VkDebugReportCallbackEXT *pCallback)
{
auto func=(PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(instance,"vkCreateDebugReportCallbackEXT");
if(func)
{
func(instance,pCreateInfo,pAllocator,pCallback);
return(true);
}
else
{
return(false);
}
}
bool DestroyDebugReportCallbackEXT(VkInstance instance,VkDebugReportCallbackEXT callback,const VkAllocationCallbacks *pAllocator)
{
auto func=(PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(instance,"vkDestroyDebugReportCallbackEXT");
if(func)
{
func(instance,callback,pAllocator);
return(true);
}
else
{
return(false);
}
}
VKAPI_ATTR VkBool32 VKAPI_CALL dbgFunc(VkDebugReportFlagsEXT msgFlags,VkDebugReportObjectTypeEXT objType,uint64_t srcObject,
size_t location,int32_t msgCode,const char *pLayerPrefix,const char *pMsg,
void *pUserData)
{
if(msgFlags&VK_DEBUG_REPORT_ERROR_BIT_EXT)
{
std::cout<<"ERROR: ";
}
else if(msgFlags&VK_DEBUG_REPORT_WARNING_BIT_EXT)
{
std::cout<<"WARNING: ";
}
else if(msgFlags&VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)
{
std::cout<<"PERFORMANCE WARNING: ";
}
else if(msgFlags&VK_DEBUG_REPORT_INFORMATION_BIT_EXT)
{
std::cout<<"INFO: ";
}
else if(msgFlags&VK_DEBUG_REPORT_DEBUG_BIT_EXT)
{
std::cout<<"DEBUG: ";
}
std::cout<<"["<<pLayerPrefix<<"] Code "<<msgCode<<" : "<<pMsg<<std::endl;
/*
* false indicates that layer should not bail-out of an
* API call that had validation failures. This may mean that the
* app dies inside the driver due to invalid parameter(s).
* That's what would happen without validation layers, so we'll
* keep that behavior here.
*/
return false;
}
}//namespace
virtual bool Init(VkInstance);
debug_report_callback=VK_NULL_HANDLE;
{
VkDebugReportCallbackCreateInfoEXT create_info;
create_info.sType =VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
create_info.pNext =nullptr;
create_info.flags =VK_DEBUG_REPORT_ERROR_BIT_EXT
|VK_DEBUG_REPORT_WARNING_BIT_EXT
|VK_DEBUG_REPORT_DEBUG_BIT_EXT
|VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
create_info.pfnCallback =dbgFunc;
create_info.pUserData =nullptr;
CreateDebugReportCallbackEXT(inst,&create_info,nullptr,&debug_report_callback);
}
debug_messenger=VK_NULL_HANDLE;
{
VkDebugUtilsMessengerCreateInfoEXT createInfo;
createInfo.sType =VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
createInfo.pNext =nullptr;
createInfo.flags =0;
createInfo.messageSeverity =VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
|VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
|VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
createInfo.messageType =VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
|VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
|VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
createInfo.pfnUserCallback =debugCallback;
createInfo.pUserData =nullptr;
CreateDebugUtilsMessengerEXT(inst,&createInfo,nullptr,&debug_messenger);
}
void close()
{
if(debug_messenger)
DestroyDebugUtilsMessengerEXT(inst,debug_messenger,nullptr);
if(debug_report_callback)
DestroyDebugReportCallbackEXT(inst,debug_report_callback,nullptr);
}

View File

@ -6,128 +6,12 @@
VK_NAMESPACE_BEGIN
Device *CreateRenderDevice(VkInstance,const PhysicalDevice *,Window *);
namespace
{
VkResult CreateDebugUtilsMessengerEXT(VkInstance instance,const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,const VkAllocationCallbacks *pAllocator,VkDebugUtilsMessengerEXT *pDebugMessenger)
{
auto func=(PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance,"vkCreateDebugUtilsMessengerEXT");
if(func)
{
return func(instance,pCreateInfo,pAllocator,pDebugMessenger);
}
else
{
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
}
void DestroyDebugUtilsMessengerEXT(VkInstance instance,VkDebugUtilsMessengerEXT debugMessenger,const VkAllocationCallbacks *pAllocator)
{
auto func=(PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance,"vkDestroyDebugUtilsMessengerEXT");
if(func)
{
func(instance,debugMessenger,pAllocator);
}
}
VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,VkDebugUtilsMessageTypeFlagsEXT messageType,const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,void *pUserData)
{
if(messageSeverity&VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
{
std::cout<<"ERROR: "<<pCallbackData->pMessage<<std::endl;
}
else
if(messageSeverity&VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
{
std::cout<<"WARNING: "<<pCallbackData->pMessage<<std::endl;
}
else
if(messageSeverity&VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT)
{
std::cout<<"INFO: "<<pCallbackData->pMessage<<std::endl;
}
else
if(messageSeverity&VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT)
{
std::cout<<"VERBOSE: "<<pCallbackData->pMessage<<std::endl;
}
else
std::cerr<<"validation layer: "<<pCallbackData->pMessage<<std::endl;
return VK_FALSE;
}
bool CreateDebugReportCallbackEXT(VkInstance instance,const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,const VkAllocationCallbacks *pAllocator,VkDebugReportCallbackEXT *pCallback)
{
auto func=(PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(instance,"vkCreateDebugReportCallbackEXT");
if(func)
{
func(instance,pCreateInfo,pAllocator,pCallback);
return(true);
}
else
{
return(false);
}
}
bool DestroyDebugReportCallbackEXT(VkInstance instance,VkDebugReportCallbackEXT callback,const VkAllocationCallbacks *pAllocator)
{
auto func=(PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(instance,"vkDestroyDebugReportCallbackEXT");
if(func)
{
func(instance,callback,pAllocator);
return(true);
}
else
{
return(false);
}
}
VKAPI_ATTR VkBool32 VKAPI_CALL dbgFunc(VkDebugReportFlagsEXT msgFlags,VkDebugReportObjectTypeEXT objType,uint64_t srcObject,
size_t location,int32_t msgCode,const char *pLayerPrefix,const char *pMsg,
void *pUserData)
{
if(msgFlags&VK_DEBUG_REPORT_ERROR_BIT_EXT)
{
std::cout<<"ERROR: ";
}
else if(msgFlags&VK_DEBUG_REPORT_WARNING_BIT_EXT)
{
std::cout<<"WARNING: ";
}
else if(msgFlags&VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)
{
std::cout<<"PERFORMANCE WARNING: ";
}
else if(msgFlags&VK_DEBUG_REPORT_INFORMATION_BIT_EXT)
{
std::cout<<"INFO: ";
}
else if(msgFlags&VK_DEBUG_REPORT_DEBUG_BIT_EXT)
{
std::cout<<"DEBUG: ";
}
std::cout<<"["<<pLayerPrefix<<"] Code "<<msgCode<<" : "<<pMsg<<std::endl;
/*
* false indicates that layer should not bail-out of an
* API call that had validation failures. This may mean that the
* app dies inside the driver due to invalid parameter(s).
* That's what would happen without validation layers, so we'll
* keep that behavior here.
*/
return false;
}
}//namespace
Instance *CreateInstance(const UTF8String &app_name)
Instance *CreateInstance(const UTF8String &app_name,VKDebugOut *do)
{
VkApplicationInfo app_info;
VkInstanceCreateInfo inst_info;
CharPointerList ext_list;
CharPointerList validation_list;
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pNext = nullptr;
@ -142,108 +26,36 @@ Instance *CreateInstance(const UTF8String &app_name)
ext_list.Add(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
ext_list.Add(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
const char *validation_layers[]=
{
// "VK_LAYER_LUNARG_api_dump",
// "VK_LAYER_LUNARG_assistant_layer",
"VK_LAYER_LUNARG_core_validation",
// "VK_LAYER_LUNARG_device_simulation",
// "VK_LAYER_LUNARG_monitor",
"VK_LAYER_LUNARG_object_tracker",
"VK_LAYER_LUNARG_standard_validation",
"VK_LAYER_LUNARG_parameter_validation",
// "VK_LAYER_LUNARG_vktrace",
"VK_LAYER_RENDERDOC_Capture",
validation_list.Add("VK_LAYER_KHRONOS_validation");
validation_list.Add("VK_LAYER_LUNARG_standard_validation");
validation_list.Add("VK_LAYER_RENDERDOC_Capture");
// "VK_LAYER_KHRONOS_validation",
// "VK_LAYER_NV_nsight-sys",
// "VK_LAYER_GOOGLE_unique_objects",
// "VK_LAYER_GOOGLE_threading"
};
inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
inst_info.pNext = nullptr;
inst_info.flags = 0;
inst_info.pApplicationInfo = &app_info;
inst_info.enabledExtensionCount = ext_list.GetCount();
inst_info.ppEnabledExtensionNames = ext_list.GetData();
inst_info.enabledLayerCount = sizeof(validation_layers)/sizeof(const char *);
inst_info.ppEnabledLayerNames = validation_layers;
inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
inst_info.pNext = nullptr;
inst_info.flags = 0;
inst_info.pApplicationInfo = &app_info;
inst_info.enabledExtensionCount = ext_list.GetCount();
inst_info.ppEnabledExtensionNames = ext_list.GetData();
inst_info.enabledLayerCount = validation_list.GetCount();
inst_info.ppEnabledLayerNames = validation_list.GetData();
VkInstance inst;
if(vkCreateInstance(&inst_info,nullptr,&inst)==VK_SUCCESS)
return(new Instance(inst,ext_list));
{
do->Init(inst);
return(new Instance(inst,ext_list,do));
}
return(nullptr);
}
Instance::Instance(VkInstance i,CharPointerList &el)
Instance::Instance(VkInstance i,CharPointerList &el,VKDebugOut *do)
{
inst=i;
ext_list=el;
{
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount,nullptr);
layer_properties.SetCount(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount,layer_properties.GetData());
debug_out(layer_properties);
}
{
uint32_t prop_count;
vkEnumerateInstanceExtensionProperties(nullptr,&prop_count,nullptr);
extension_properties.SetCount(prop_count);
vkEnumerateInstanceExtensionProperties(nullptr,&prop_count,extension_properties.GetData());
debug_out(extension_properties);
}
debug_report_callback=VK_NULL_HANDLE;
{
VkDebugReportCallbackCreateInfoEXT create_info;
create_info.sType =VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
create_info.pNext =nullptr;
create_info.flags =VK_DEBUG_REPORT_ERROR_BIT_EXT
|VK_DEBUG_REPORT_WARNING_BIT_EXT
|VK_DEBUG_REPORT_DEBUG_BIT_EXT
|VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
create_info.pfnCallback =dbgFunc;
create_info.pUserData =nullptr;
CreateDebugReportCallbackEXT(inst,&create_info,nullptr,&debug_report_callback);
}
debug_messenger=VK_NULL_HANDLE;
{
VkDebugUtilsMessengerCreateInfoEXT createInfo;
createInfo.sType =VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
createInfo.pNext =nullptr;
createInfo.flags =0;
createInfo.messageSeverity =VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
|VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
|VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
createInfo.messageType =VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
|VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
|VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
createInfo.pfnUserCallback =debugCallback;
createInfo.pUserData =nullptr;
CreateDebugUtilsMessengerEXT(inst,&createInfo,nullptr,&debug_messenger);
}
debug_out=do;
uint32_t gpu_count = 1;
@ -260,34 +72,13 @@ Instance::Instance(VkInstance i,CharPointerList &el)
}
Instance::~Instance()
{
SAFE_CLEAR(debug_out);
physical_devices.Clear();
if(debug_messenger)
DestroyDebugUtilsMessengerEXT(inst,debug_messenger,nullptr);
if(debug_report_callback)
DestroyDebugReportCallbackEXT(inst,debug_report_callback,nullptr);
vkDestroyInstance(inst,nullptr);
}
const bool Instance::CheckLayerSupport(const UTF8String &layer_name)const
{
const uint32_t count=layer_properties.GetCount();
VkLayerProperties *lp=layer_properties.GetData();
for(uint32_t i=0;i<count;i++)
{
if(layer_name==lp->layerName)
return(true);
++lp;
}
return(false);
}
const PhysicalDevice *Instance::GetDevice(VkPhysicalDeviceType type)const
{
const uint32_t count=physical_devices.GetCount();

View File

@ -0,0 +1,58 @@
#include<hgl/graph/vulkan/VK.h>
VK_NAMESPACE_BEGIN
namespace
{
static List<VkLayerProperties> layer_properties;
static List<VkExtensionProperties> extension_properties;
}//namespace
const List<VkLayerProperties> &GetLayerProperties(){return layer_properties;}
const List<VkExtensionProperties> &GetExtensionProperties(){return extension_properties;}
void InitVulkanProperties()
{
layer_properties.Clear();
extension_properties.Clear();
{
uint32_t layer_count;
vkEnumerateInstanceLayerProperties(&layer_count,nullptr);
layer_properties.SetCount(layer_count);
vkEnumerateInstanceLayerProperties(&layer_count,layer_properties.GetData());
debug_out(layer_properties);
}
{
uint32_t prop_count;
vkEnumerateInstanceExtensionProperties(nullptr,&prop_count,nullptr);
extension_properties.SetCount(prop_count);
vkEnumerateInstanceExtensionProperties(nullptr,&prop_count,extension_properties.GetData());
debug_out(extension_properties);
}
}
const bool CheckLayerSupport(const char *layer_name)
{
if(!layer_name||!*layer_name)
return(false);
const uint32_t count=layer_properties.GetCount();
VkLayerProperties *lp=layer_properties.GetData();
for(uint32_t i=0;i<count;i++)
{
if(strcmp(layer_name,lp->layerName)==0)
return(true);
++lp;
}
return(false);
}
VK_NAMESPACE_END

View File

@ -0,0 +1,2 @@
add_executable(ShaderCompiler main.cpp)
target_link_libraries((ShaderCompiler PRIVATE ${ULRE}

View File

View File

@ -0,0 +1,7 @@
add_executable(TexConv MainUnit.cpp ${HGL_GRAPHICS_MAIN_SOURCE})
target_compile_definitions(TexConv PRIVATE "-DIL_STATIC_LIB")
target_include_directories(TexConv PRIVATE ${CMGDK_PATH}/src/PlugIn/Image.Monolayer/DevIL/include)
target_link_libraries(TexConv ${HGL_GRAPHICS_LIB} DevIL)
SET_TARGET_PROPERTIES(TexConv PROPERTIES WIN32_EXECUTABLE "true")

View File

@ -0,0 +1,708 @@
#include<hgl/Graphics.h>
#include<hgl/graph/Render.h> //SetClearColor
#include<hgl/graph/Shader.h> //GLSL
#include<hgl/graph/Texture.h> //Texture
#include<hgl/graph/Material.h> //Material
#include<hgl/graph/VertexBuffer.h> //VB3f/VB4f
#include<hgl/graph/Renderable.h> //Renderable
#include<hgl/Time.h> //GetMicroTime
#include<hgl/io/FileOutputStream.h>
#include<hgl/ut/CmdParse.h>
#include<hgl/graph/Bitmap.h>
#include<hgl/Str.h>
#include<hgl/Info.h> //GetString
#include<IL/il.h>
#include<IL/ilu.h>
#include<string.h>
using namespace hgl;
using namespace hgl::io;
using namespace hgl::util;
using namespace hgl::graph;
using namespace hgl::filesystem;
const TextureFormat *default_r8 =&TextureFormatInfoList[HGL_SF_R8];
const TextureFormat *default_rg8 =&TextureFormatInfoList[HGL_SF_RG8];
const TextureFormat *default_rgb8 =&TextureFormatInfoList[HGL_SF_RGB8];
const TextureFormat *default_rgba8 =&TextureFormatInfoList[HGL_SF_RGBA8];
const TextureFormat *default_r16 =&TextureFormatInfoList[HGL_SF_R16];
const TextureFormat *default_r32f =&TextureFormatInfoList[HGL_SF_R32F];
//--------------------------------------------------------------------------------------------------
const TextureFormat * glfmt[4] ={NULL,NULL,NULL,NULL}; //选中格式
bool gen_mipmaps =false; //是否产生mipmaps
bool only_view =false; //仅显示
bool use_color_key=false; //是否使用ColorKey
uint8 color_key[3]; //ColorKey颜色
const float texcoord[] ={0.0f,0.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f, 0.0f,1.0f};
VertexArray * va =NULL;
Renderable * render_obj =NULL;
Material * mtl =NULL;
Texture2D * tex =NULL;
VB2f * vertex =NULL;
//--------------------------------------------------------------------------------------------------
//OpenIL数据
uint il_index=0; //图片索引
int il_width,il_height,il_bit;
uint il_format=0;
uint il_type=0;
uint il_pal_type=0;
uint il_pal_color_num=0;
//--------------------------------------------------------------------------------------------------
//统计数据
int max_pixels=0; //最大像素数
uint8 *image_data=NULL; //图像数据
int max_bytes=0; //最大字节数
uint8 *texture_data=NULL; //贴图数据
int convert_count=0; //转换总数
int bytes_count=0; //总字节数
int cbytes_count=0; //转换后总字节数
//--------------------------------------------------------------------------------------------------
const TextureFormat *CheckOpenGLCoreFormat(const CmdParse &cmd,const os_char *flag,const TextureFormat *default_tf)
{
OSString fmtstr;
if(!cmd.GetString(flag,fmtstr))return(nullptr);
#if HGL_OS==HGL_OS_Windows
UTF8String str=to_u8(fmtstr);
const TextureFormat *result=GetTextureFormat(str.c_str());
#else
const TextureFormat *result=GetTextureFormat(fmtstr.c_str());
#endif//HGL_OS==HGL_OS_Windows
if(result)return(result);
return default_tf;
}
void CheckOpenGLCoreFormat(const CmdParse &cmd)
{
//指定格式
glfmt[0]=CheckOpenGLCoreFormat(cmd,OS_TEXT("/R:"), &TextureFormatInfoList[HGL_SF_R8]);
glfmt[1]=CheckOpenGLCoreFormat(cmd,OS_TEXT("/RG:"), &TextureFormatInfoList[HGL_SF_RG8]);
glfmt[2]=CheckOpenGLCoreFormat(cmd,OS_TEXT("/RGB:"), &TextureFormatInfoList[HGL_SF_RGB8]);
glfmt[3]=CheckOpenGLCoreFormat(cmd,OS_TEXT("/RGBA:"), &TextureFormatInfoList[HGL_SF_RGBA8]);
}
void CheckColorKey(const CmdParse &cmd)
{
OSString ckstr;
if(!cmd.GetString(OS_TEXT("/ColorKey:"),ckstr))return;
os_char rgbstr[6];
hgl_cpy(rgbstr,ckstr.c_str(),6); //注意hgl_cpy是跨类型复制的不要替换成strcpy或memcpy
ParseHexStr(color_key[0],rgbstr+0);
ParseHexStr(color_key[1],rgbstr+2);
ParseHexStr(color_key[2],rgbstr+4);
use_color_key=true;
}
bool CheckSameAlpha(uint8 *data,uint count)
{
uint8 *p=data;
while(count--)
{
if(*p!=*data)return(false);
p++;
}
return(true);
}
/**
* RGB数据是否一致
*/
bool CheckSameRGB(uint8 *data,int color,uint count)
{
uint8 *p=data;
while(count--)
{
if(memcmp(data,p,color-1))
return(false);
p+=color;
}
return(true);
}
void MixLA(uint8 *lum,uint8 *alpha,int size)
{
int i;
for(i=0;i<size;i++)
{
lum++;
*lum++=*alpha++;
}
}
void MixRGBA(uint8 *rgba,uint8 *alpha,int size)
{
int i;
for(i=0;i<size;i++)
{
rgba+=3;
*rgba++=*alpha++;
}
}
void FlipData(uint8 *data,int line_bytes,int row_number)
{
int i;
uint8 *temp=new uint8[line_bytes];
uint8 *end=data+line_bytes*(row_number-1);
for(i=0;i<row_number/2;i++)
{
memcpy(temp,data,line_bytes);
memcpy(data,end,line_bytes);
memcpy(end,temp,line_bytes);
data+=line_bytes;
end-=line_bytes;
}
delete[] temp;
}
void ConvertPixelFormat()
{
uint fmt=il_format;
if(il_format==IL_BGR)
fmt=IL_RGB;
else
if(il_format==IL_BGRA)
fmt=IL_RGBA;
if(il_format==IL_RGBA||il_format==IL_BGRA||il_format==IL_LUMINANCE_ALPHA)
{
uint8 *alpha=ilGetAlpha(IL_UNSIGNED_BYTE);
uint count=il_width*il_height;
uint color=(il_format==IL_LUMINANCE_ALPHA?2:3);
if(CheckSameAlpha(alpha,count)) //检测ALPHA全部一样的将RGBA转为RGB,将LA转为L
{
if(il_format==IL_RGBA||il_format==IL_BGRA)
{
fmt=IL_RGB;
}
else
if(il_format==IL_LUMINANCE_ALPHA)
{
fmt=IL_LUMINANCE;
}
}
else //如果ALPHA不同检测颜色是否相同如果相同只留ALPHA
{
uint8 *data=ilGetData();
uint count=il_width*il_height;
if(CheckSameRGB(data,color,count))
fmt=IL_ALPHA;
}
if(alpha)free(alpha);
}
if(il_format==IL_RGB||il_format==IL_BGR)
{
if(CheckMono(ilGetData(),3,il_width,il_height))
fmt=IL_LUMINANCE;
}
if(fmt!=IL_ALPHA //只有ALPHA就不检测
&&(il_format==IL_RGBA||il_format==IL_BGRA))
{
if(CheckMono(ilGetData(),4,il_width,il_height))
{
if(fmt==IL_RGB) //前面一段代码已经将alpha砍掉了
fmt=IL_LUMINANCE;
else
fmt=IL_LUMINANCE_ALPHA;
}
}
if(fmt!=il_format)
{
ilConvertImage(fmt,il_type);
il_format=fmt;
}
}
void CheckPalette()
{
uint pal=il_pal_type;
if(il_pal_type==IL_PAL_BGR24||il_pal_type==IL_PAL_BGR32||il_pal_type==IL_PAL_RGB32)
pal=IL_PAL_RGB24;
else
if(il_pal_type==IL_PAL_BGRA32)
pal=IL_PAL_RGBA32;
if(pal!=il_pal_type)
{
ilConvertPal(pal);
il_pal_type=pal;
}
}
void SaveTexture2DToFile(const os_char *filename,void *texture_data,uint width,uint height,const char *format,uint bytes,bool include_color_key)
{
os_char tex_fn[HGL_MAX_PATH];
char fmt_str[17];
replace_extname(tex_fn,filename,HGL_MAX_PATH,OS_TEXT("Tex2D"));
FileOutputStream fs;
DataOutputStream *dos;
if(!fs.CreateTrunc(tex_fn))
{
LOG_INFO(OS_TEXT("\tCreateFile(")+OSString(tex_fn)+OS_TEXT(") error!"));
return;
}
dos=new LEDataOutputStream(&fs);
memset(fmt_str,0,17);
hgl::strcpy(fmt_str,16,format);
dos->Write("Tex\x1A",4);
dos->WriteUint8(1); //版本号
dos->WriteBool(false); //是否有mipmaps
dos->Write(fmt_str,16); //格式
dos->WriteUint32(bytes); //字节数
if(include_color_key)
{
dos->WriteBool(true);
dos->WriteUint8(color_key,3);
LOG_INFO(OS_TEXT("\tColor Key: true"));
}
else
{
dos->Write("\0\0\0\0",4);
}
dos->WriteUint32(width); //宽
dos->WriteUint32(height); //高
dos->Write(texture_data,bytes);
delete dos;
LOG_INFO(OS_TEXT("\tSave to ")+OSString(tex_fn));
}
int ConvertImage(const os_char *filename)
{
bool confirm_color_key=false;
uint pixels=0;
const TextureFormat *curfmt=nullptr;
const TextureFormat *tarfmt=nullptr;
LOG_INFO(OS_TEXT("File: ")+OSString(filename));
ilGenImages(1,&il_index);
ilBindImage(il_index);
if(ilLoadImage(filename))
{
il_width =ilGetInteger(IL_IMAGE_WIDTH);
il_height =ilGetInteger(IL_IMAGE_HEIGHT);
il_bit =ilGetInteger(IL_IMAGE_BITS_PER_PIXEL);
il_format =ilGetInteger(IL_IMAGE_FORMAT);
il_type =ilGetInteger(IL_IMAGE_TYPE);
if(ilGetInteger(IL_IMAGE_ORIGIN)==IL_ORIGIN_LOWER_LEFT)
iluFlipImage();
LOG_INFO(OS_TEXT("\twidth: ")+OSString(il_width));
LOG_INFO(OS_TEXT("\theight: ")+OSString(il_height));
pixels=il_width*il_height;
if(pixels>max_pixels)
SAFE_CLEAR_ARRAY(image_data);
if(!image_data)
{
image_data=new uint8[pixels*4*4];
max_pixels=pixels;
}
if(il_format!=IL_COLOR_INDEX)
{
if(il_format==IL_LUMINANCE )
{
if(il_type==IL_UNSIGNED_BYTE)
curfmt=default_r8;
else
if(il_type==IL_UNSIGNED_SHORT)
curfmt=default_r16;
else
if(il_type==IL_FLOAT)
curfmt=default_r32f;
else
{
ilConvertImage(IL_LUMINANCE,IL_UNSIGNED_BYTE);
il_type=IL_UNSIGNED_BYTE;
curfmt=default_r8;
}
tarfmt=(glfmt[0]?glfmt[0]:curfmt);
memcpy(image_data,ilGetData(),pixels*curfmt->source_bytes);
}
else
{
if(il_type!=IL_UNSIGNED_BYTE)
{
ilConvertImage(il_format,IL_UNSIGNED_BYTE);
il_type=IL_UNSIGNED_BYTE;
}
ConvertPixelFormat();
if(il_format==IL_LUMINANCE )
{
curfmt=default_r8;
tarfmt=(glfmt[0]?glfmt[0]:curfmt);
memcpy(image_data,ilGetData(),pixels);
}
else
if(il_format==IL_ALPHA )
{
curfmt=default_r8;
tarfmt=(glfmt[0]?glfmt[0]:curfmt);
memcpy(image_data,ilGetAlpha(GL_UNSIGNED_BYTE),pixels);
}
else
if(il_format==IL_LUMINANCE_ALPHA)
{
curfmt=default_rg8;
tarfmt=(glfmt[1]?glfmt[1]:curfmt);
uint8 *alpha=ilGetAlpha(GL_UNSIGNED_BYTE);
memcpy(image_data,ilGetData(),pixels*2);
MixLA(image_data,alpha,pixels);
free(alpha);
}
else
if(il_format==IL_RGB )
{
curfmt=default_rgb8;
tarfmt=(glfmt[2]?glfmt[2]:curfmt);
memcpy(image_data,ilGetData(),pixels*3);
if(use_color_key) //检测ColorKey是否存在
{
unsigned char *p=image_data;
for(int i=0;i<pixels;i++)
{
if((image_data[0]==color_key[0])
&&(image_data[1]==color_key[1])
&&(image_data[2]==color_key[2]))
{
confirm_color_key=true;
break;
}
p+=3;
}
}
}
else
if(il_format==IL_RGBA )
{
curfmt=default_rgba8;
tarfmt=(glfmt[3]?glfmt[3]:curfmt);
uint8 *alpha=ilGetAlpha(GL_UNSIGNED_BYTE);
memcpy(image_data,ilGetData(),pixels*4);
MixRGBA(image_data,alpha,pixels);
free(alpha);
}
else
{
curfmt=NULL;
tarfmt=NULL;
LOG_INFO("\tsource format error");
ilDeleteImages(1,&il_index);
return(0);
}
}//LUMINANCE
tex->SetImage(il_width,il_height,image_data,pixels*curfmt->source_bytes,curfmt->tsf,tarfmt->video_format);
#if HGL_OS == HGL_OS_Windows
LOG_INFO(OS_TEXT("\tcolor format = ")+to_u16(curfmt->name)+OS_TEXT(" bytes = ")+OSString(curfmt->source_bytes*il_width*il_height));
LOG_INFO(OS_TEXT("\ttarget format = ")+to_u16(tarfmt->name));
#else
LOG_INFO(OS_TEXT("\tcolor format = ")+OSString(curfmt->name)+OS_TEXT(" bytes = ")+OSString(curfmt->source_bytes*il_width*il_height));
LOG_INFO(OS_TEXT("\ttarget format = ")+OSString(tarfmt->name));
#endif//HGL_OS == HGL_OS_Windows
int bytes=tex->GetImage(NULL,tarfmt->tsf);
if(bytes>0)
{
LOG_INFO(OS_TEXT("\toutput bytes = ")+OSString(bytes));
if(bytes>max_bytes)
SAFE_CLEAR_ARRAY(texture_data);
if(!texture_data)
{
texture_data=new uint8[bytes];
max_bytes=bytes;
}
tex->GetImage(texture_data,tarfmt->tsf);
SaveTexture2DToFile(filename,texture_data,il_width,il_height,tarfmt->name,bytes,confirm_color_key);
convert_count++;
bytes_count+=il_width*il_height*curfmt->source_bytes;
cbytes_count+=bytes;
}
}
// else //索引色贴图
// {
// il_pal_type =ilGetInteger(IL_PALETTE_TYPE); //调色板类型
// il_pal_color_num=ilGetInteger(IL_PALETTE_NUM_COLS); //颜色数量
//
// LOG_INFO(OS_TEXT("\tpal color number = ")+OSString(il_pal_color_num));
//
// if(il_pal_color_num==16||il_pal_color_num==256)
// {
// CheckPalette();
//
// if(il_pal_type==IL_PAL_RGB24 &&il_pal_color_num== 16)curfmt=GetFormat("16RGB");else
//
// if(il_pal_type==IL_PAL_RGBA32&&il_pal_color_num== 16)curfmt=GetFormat("16RGBA");else
// if(il_pal_type==IL_PAL_RGB24 &&il_pal_color_num==256)curfmt=GetFormat("256RGB");else
// if(il_pal_type==IL_PAL_RGBA32&&il_pal_color_num==256)curfmt=GetFormat("256RGBA");else
// curfmt=NULL;
//
// if(curfmt)
// LOG_INFO(OS_TEXT("\tcolor format = ")+OSString(curfmt->name));
// }
// else
// curfmt=NULL;
// }
if(!curfmt)
LOG_INFO("\tformat error!\n");
}
else
{
LOG_INFO("\tLoad File error!");
}
ilDeleteImages(1,&il_index);
return(0);
}
class EnumFileConfigApp:public EnumFileConfig
{
public:
GraphicsApplication *app;
using EnumFileConfig::EnumFileConfig;
};
void EnumConvertImage(EnumFileConfig *efc,FileInfo &fi)
{
EnumFileConfigApp *efca=(EnumFileConfigApp *)efc;
GraphicsApplication *gapp=efca->app;
ConvertImage(fi.fullname);
render_obj->AutoCreateShader();
ClearColorDepthBuffer();
const int l=(GetScreenWidth()-il_width)/2;
const int t=(GetScreenHeight()-il_height)/2;
vertex->Begin();
vertex->WriteRect(l,t,il_width,il_height);
vertex->End();
DirectRender2D(render_obj);
gapp->SwapBuffer();
gapp->WaitActive();
}
HGL_GRAPHICS_MAIN(sii,app,args)
{
CmdParse cmd(args);
bool sub=false;
sii.info.ProjectName=U8_TEXT("贴图转换");
sii.info.ProjectCode=OS_TEXT("Texture Converter");
sii.info.ProjectVersion=U8_TEXT("1.01");
if(!app.Init(&sii))return(-1);
LOG_INFO("argc="+UTF8String(args.GetCount()));
for(int i=0;i<args.GetCount();i++)
LOG_INFO(OS_TEXT("argv[")+OSString(i)+OS_TEXT("] ")+args[i]);
if(args.GetCount()<1)
{
char space[33];
constexpr uint STR_HINT_MAX=128+(32*HGL_SF_END);
char *hint=new char[STR_HINT_MAX];
hgl::strcpy(hint,STR_HINT_MAX,
"Command format:\n"
"\tTexConv <filename or pathname> [/s] [/view] [/R:?] [/RG:?] [/RGB:?] [/RGBA:?]\n"
"\n"
"Params:\n"
"\t/s : proc sub-directory\n"
"\n"
"support format:\n\n");
int count=0;
int len;
memset(space,' ',32);
space[32]=0;
for(int i=HGL_SF_NONE+1;i<HGL_SF_END;i++)
{
if(TextureFormatInfoList[i].name[0]==0)
{
if(count==0)
hgl::strcat(hint,STR_HINT_MAX,'\n');
else
hgl::strcat(hint,STR_HINT_MAX,"\n\n",2);
count=0;
continue;
}
len=hgl::strlen(TextureFormatInfoList[i].name);
hgl::strcat(hint,STR_HINT_MAX,TextureFormatInfoList[i].name,len);
hgl::strcat(hint,STR_HINT_MAX,space,16-len);
++count;
if(count==4)
{
hgl::strcat(hint,STR_HINT_MAX,'\n');
count=0;
}
else
hgl::strcat(hint,STR_HINT_MAX,'\t');
}
//MessageBoxA(nullptr,hint,"TexConv",MB_OK|MB_ICONINFORMATION);
LOG_ERROR(hint);
delete[] hint;
return(0);
}
if(cmd.Find(OS_TEXT("/s"))!=-1)sub=true; //检测是否处理子目录
if(cmd.Find(OS_TEXT("/view"))!=-1)only_view=true; //检测是否仅显示
if(cmd.Find(OS_TEXT("/mip"))!=-1)gen_mipmaps=true; //检测是否生成mipmaps
CheckColorKey(cmd);
CheckOpenGLCoreFormat(cmd); //检测推荐格式
ilInit();
OSString cur_path=info::GetString(info::hfsStartPath);
va=new VertexArray(HGL_PRIM_TRIANGLES);
va->SetVertexBuffer(vbtVertex,vertex=new VB2f(6,0,HGL_DYNAMIC_DRAW));
va->SetVertexBuffer(vbtDiffuseTexCoord,new VB2f(6,texcoord));
tex=CreateTexture2D();
mtl=new Material;
mtl->SetColorMaterial(false);
mtl->SetTexture(mtcDiffuse,tex);
render_obj=new Renderable(va,mtl);
render_obj->SetMaterial(mtl);
render_obj->SetTexCoord(mtcDiffuse,vbtDiffuseTexCoord);
double start_time=GetMicroTime();
double end_time;
EnumFileConfigApp efc;
efc.app =&app;
efc.folder_name =cur_path;
efc.find_name =args[0];
efc.proc_file =true;
efc.sub_folder =sub;
efc.cb_file =EnumConvertImage;
EnumFile(&efc);
end_time=GetTime();
LOG_INFO(OS_TEXT("总计转换图片")+OSString(convert_count)
+OS_TEXT("张,总计处理原始数据")+OSString(bytes_count)
+OS_TEXT("字节,转换后")+OSString(cbytes_count)
+OS_TEXT("字节,总计耗时")+OSString(end_time-start_time)+OS_TEXT(""));
delete[] image_data;
delete[] texture_data;
delete tex;
delete render_obj;
ilShutDown();
return(0);
}