OpenGL之多紋理映射

OpenGL之多紋理映射

OpenGL可同時對多邊形映射多個紋理,稱為『多紋理映射』. 它是OpenGL的可選擴展實現,並非所有的OpenGL都有實現.『OpenGL API的所有擴展必須得到ARB(OpenGL體系評審委員會)的認可』,在進行多紋理映射時,每個紋理單元都將映射結果傳遞給下個紋理單元,直至所有的紋理的紋理單元都進行映射(最終結果)演示程式:下载

多紋理映射分為四個步驟:
1.判斷是否支持『多紋理映射』
2.讀取擴展函式的指針
3.建立紋理單元
4.設置紋理坐標

定義多紋理映射結構

typedef struct MULTITEXTURE_TYP {

TEXTURE texture0;

TEXTURE texture1;

}MULTITEXTURE,*MULTITEXTURE_PTR;

1.驗證當前版本的OpenGL是否支持『多紋理映射』

函式 簡介
glGetString(GL_EXTENSIONS) 獲取OpenGL所支持的所有擴展函式

返回以空格隔開的字符串列表

GL_ARB_multitexture 查找(GL_ARB_multitexture)判斷是否支持『多紋理映射』

判斷是否支持某一擴展函式

bool Extensions_OpenGL(const char * name)

{

char * extensions;

int index = 0;

int length,n;

extensions = (char*)glGetString(GL_EXTENSIONS);// 擴展函式

length = strlen(name);// 長度

while (extensions[index] != NULL)// 循環查找

{

n = strcspn(extensions + index, ” “);// 查找空格

if (n == length && strncmp(extensions + index, name, length) == 0)// 比較

return true;

index = index + n + 1; // 跳過空格

}

return false;

}

2.讀取擴展函式的指針

函式 簡介
PROC wglGetProcAddress(LPCSTR lpszProc); 返回擴展函式的地址

 

擴展函式定義 簡介
typedef void (APIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); 為多紋理映射設置紋理座標
typedef void (APIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture); 設置當前的紋理單元
typedef void (APIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); 設置選擇當前的紋理單位,以便用頂點數組指定紋理坐標數據

初此化多紋理映射

PFNGLMULTITEXCOORD2FARBPROC     glMultiTexCoord2fARB;

PFNGLACTIVETEXTUREARBPROC       glActiveTextureARB;

PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB;

void Init_Multitexture()

{// 判斷是否支持某一擴展函式

if( Extensions_OpenGL(“GL_ARB_multitexture”) )

{

glMultiTexCoord2fARB=(PFNGLMULTITEXCOORD2FARBPROC)wglGetProcAddress(“glMultiTexCoord2fARB”);

glActiveTextureARB=(PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress(“glActiveTextureARB”);

glClientActiveTextureARB=(PFNGLCLIENTACTIVETEXTUREARBPROC)wglGetProcAddress(“glClientActiveTextureARB”);

}

}

3.建立紋理單元

載入紋理並綁定 簡介
『.bmp』 『.tga』 『.pcx』 載入紋理文件
glGenTextures(1, &texture->ID);

glBindTexture(GL_TEXTURE_2D, texture->ID);

生成紋理單元綁定紋理

激活多紋理映射

void Active_Multitexture(MULTITEXTURE_PTR multitexture)

{

glActiveTextureARB(GL_TEXTURE0_ARB);

glEnable(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, multitexture->texture0.ID);// 綁定紋理

glActiveTextureARB(GL_TEXTURE1_ARB);

glEnable(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, multitexture->texture1.ID);// 綁定紋理

}

OpenGL最多支持32個紋理『GL_TEXTURE0_ARB』~『GL_TEXTURE31_ARB』

但最後通過查詢當前版本支持的最大單元量

int maxTexUnits;

glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&maxTexUnits);

 

4.設置紋理坐標

  簡介
void glMultiTexCoord2fARB(GLenum texUnit,float coords); 設置紋理坐標
texUnit: GL_TEXTURE0_ARB~GL_TEXTURE31_ARB 紋理單元索引
Coords: 紋理坐標

 

Windows之Microsoft屏幕放大鏡

Windows之Microsoft屏幕放大鏡

Windows其中一個最好用的工具是『Microsoft屏幕放大鏡』,通過win鍵與+鍵啟動.如果你有『Microsoft鼠標』可以通過安裝『IntelliPoint8.2』激活母指鍵啟動『Microsoft屏幕放大鏡』.安裝後要重啟電腦. 通過『檔案總管\控制台\所有控制台項目\滑鼠』設定『母指鍵』.在『全屏幕』下按『母指鍵』+『鼠標滑輪』用於梯相最好用.

快捷鍵 簡介
Win鍵與+鍵 方大/啟動放大鏡
Win鍵與-鍵 縮小
Win鍵與ESC鍵 關閉放大鏡
鼠標前母指鍵 啟動放大鏡/關閉放大鏡
鼠標前母指鍵+鼠標滑輪 方大/縮小(這個最好用)
CTRL+ALT+F 全屏幕
CTRL+ALT+L 透鏡
CTRL+ALT+D 以連接擴充座(分屏)
CTRL+ALT+SPACE 預覽全屏幕
CTRL+ALT+I 反色

 

Microsoft 無線霸雷鯊7000鼠標修復

Microsoft 無線霸雷鯊7000鼠標修復

鼠標輕觸開關是最容易損耗的,當鼠標出現連擊時,鼠標要準備退役,即使是最貴的鼠標使用壽命也相差唔多,就算鼠標有五年保養也不會幫你更換輕觸開關,唔信你可以試下拿它返廠.

如果你很喜歡你的滑鼠可以通過更換滑鼠的輕觸開關(如上圖),延長滑鼠使用壽命.因位兩層上錫要將它熔焊有D難度.因為『霸雷鯊7000』只有兩隻腳所以無分正負,貼緊上錫即可.

如果『霸雷鯊7000』出現斷幀可以償試拔掉其它USB設備.

 

OpenGL之讀取PCX圖檔

OpenGL之讀取PCX圖檔

PCX圖檔較常用於3D紋理,你的3D遊戲引擎無任何理由拒絕支持PCX格式的圖檔.幸好PCX格式非常簡單.渲染演示程式下載:

它主要由三部份組成:

  1. 文檔頭部
  2. 經RLE編碼的圖像數據
  3. 調色板,只用於256色
PCX文檔頭部結構 簡介
typedef struct PCX_HEADER_TAG{  
UCHAR  manufacturer; PCX標記:總是 0x0A
UCHAR  version; 版本號
UCHAR  encoding; 編碼:總為 1,使用RLE編碼
UCHAR  bits_per_pixel; 每像數所占的位數 1,2,4,8
USHORT xmin, ymin; 圖像的左下角邊界
USHORT xmax, ymax; 圖像的右上角邊界
USHORT hres; 水平分辨率
USHORT yres; 垂直分辨率
UCHAR  EGAcolors[48]; EGA(16色)調色板,這種圖檔以較小式用
UCHAR  reserved; 保留字節
UCHAR  color_planes; 色彩平面量 (24Bit圖檔為3)
USHORT bytes_per_line; 每行字節數(單個顏色分量)
USHORT palette_type; 1為灰度,2為彩色調色板
USHORT scrnw; 屏幕水平像素
USHORT scrnh; 屏幕垂直像素
UCHAR  filler[54]; 54BYTE全零
} PCX_HEADER, *PCX_HEADER_PTR;  

你需要定義新的PCX結構用於保存PCX信息.

PCX 結構
typedef struct PCX_TAG{  
int               width; 圖寬=xmax – xmin + 1
int               height; 圖高=ymax – ymin + 1
int               bitCount; 位圖像素的bits 8位,16位,24位,32位

bitCount=color_planes*bytes_per_line

PCX_PALETTEENTRY  palette[256]; 調色板,當圖檔為256色時出現
PBYTE             buffer; 圖像數據
} PCX, *PCX_PTR;  

我實現PCX解釋器支持『256色』『16BIT』兩種常見格式:

bool Load_PCX(PCX_PTR pcx,PBYTE data,int size)

{

int      index;              // 循环变量

PBYTE   image;// 图像数据

int     image_size;// 像数个数

PBYTE          RLE;//  RLE编码图像数据

PCX_HEADER_PTR  header;// 文档的头部

PCX_PALETTEENTRY_PTR  palette;// 读取PCX的调色版

header = (PCX_HEADER_PTR)data; // 文档的头部

pcx->width  = (header->xmax – header->xmin) + 1;// 图像宽度(像数)

pcx->height = (header->ymax – header->ymin) + 1;// 图像高度(像数)

pcx->bitCount = header->bits_per_pixel * header->color_planes;// 计算每像数所占的位数

RLE = data + sizeof(PCX_HEADER);

if (pcx->bitCount == 8)

{         // 分配图像记忆体

pcx->buffer = (PBYTE)malloc(pcx->width*pcx->height * 3);

image = (PBYTE)malloc(pcx->width*pcx->height);

image_size = pcx->width * pcx->height;// 图像的像素

Load_RLE_PCX(image, RLE, pcx->width, pcx->height);// RLE解码

// 读取PCX的调色版

palette = (PCX_PALETTEENTRY_PTR)(data + size – 768);// 在文件的结束的位置前移768字节即移动到调色板的开始位置

for (int i = 0; i < image_size; ++i)

{//掉转红色和绿色

index = image[i];

pcx->buffer[i*3 + 0] = palette[index].red;// 红色部分

pcx->buffer[i*3 + 1] = palette[index].green;// 取的绿色部分

pcx->buffer[i*3 + 2] = palette[index].blue;// 取的蓝色部分

}

pcx->bitCount = 24;

free(image);// 释放记忆体

}

else

if (pcx->bitCount == 24)

{// 分配图像记忆体

pcx->buffer = (PBYTE)malloc(pcx->widthpcx->height3);

Load_RLE24_PCX(pcx->buffer, RLE, pcx->width, pcx->height);// RLE解码

}

return true;

}

OpenGL之讀取PCX文檔-RLE解碼

OpenGL之讀取PCX文檔-RLE解碼

『PCX』與『BMP』同樣支持『RLE編碼』,而且支持8Bit和24Bit的『RLE編碼』渲染演示程式下載:

先講解8Bit (256色)『RLE編碼』算法:

  1. 首字節把『重複』像素的個數的最高兩BIT設為1保存, 0xC0&length
  2. 解碼時只要把首字節減192即等於『重複』個數,或者data& 0x3F提取最低六位.
  3. 次字節寫入重複的像素值
  4. 並且『重複』像素的最大長度為63,因為255(0xff)-192(0xc0)=63
  5. 如果像素大於192,把像數當成『不重複』的像素直接保存
  6. 『不重複』的像素直接保存

PCX的24BIT圖檔同樣使用『RLE編碼』,但網絡上PCX的24Bit『RLE解碼』算法大多都是不正確,

24Bit『RLE編碼』算法:

  1. 24BIT算法8Bit基本一致.最大分別是它對每行像素的RGB值進行分解後再進行RLE編碼
  2. 數據:RGB RGB RGB
  3. 分解:RRR GGG BBB
  4. RLE:3R 3G 3B

 

8Bit (256色)『RLE解碼』C代碼:

void Load_RLE_PCX(PBYTE image, PBYTE data, int width,int height)

{

BYTE value;

int length;// 像素個數

int data_index = 0;// RLE索引

int image_index = 0;// 圖像索引

int image_size = width * height;

while (image_index < image_size)// 遍歷壓縮後數據

{// 判斷是否RLE編碼

if (data[data_index] >= 192 && data[data_index] <= 255)

{// 重複的數據

length = data[data_index] – 192;// 長度

value  = data[data_index + 1];// 索引值

while (length > 0)

{

image[image_index] = value;

++image_index;

–length;

}

data_index = data_index + 2;

}

else

{// 不重的數據

image[image_index] = data[data_index];

++image_index;

++data_index;

}

}

}

 

24Bit『RLE解碼』C代碼:

void Load_RLE24_PCX(PBYTE image, PBYTE data, int width, int height)

{

BYTE value;

int length = 0;// 像素個數

int data_index = 0; // RLE索引

int image_index = 0; // 圖像索引

int image_size = width * height;

for (image_index = 0; image_index < image_size; image_index = image_index + width)// 遍歷RLE編碼數據

{

for (int i = 0, x = 0; i < 3 && x < width; )

{// 判斷是否RLE編碼

if (data[data_index] >= 192 && data[data_index] <= 255)

{// 讀取重複的數據

length = data[data_index] – 192;// 數據的長度

//length = data[data_index] & 0x3F;

value = data[data_index + 1];// 數值

data_index = data_index + 2; // RLE編碼索引

while (length > 0)

{

if (x >= width)

{

++i;

x = 0;// 以達到行尾跳轉 i加1 x設0

}

image[(image_index + x) * 3 + i] = value;//寫入重複數據

++x;// x座標索引加一

–length;// 重複數據量減一

}

}

else

{// 無壓縮的數據

image[(image_index + x) * 3 + i] = data[data_index];// 寫入

++data_index; // RLE編碼索引

++x;

}

if (x >= width)

{

++i;

x = 0;

}

}

}

return;

}

 

OpenGL之紋理地形

OpenGL之紋理地形

地形文檔其實就是灰度圖,每一位灰度(0~255)對應其高度值,由高度值組成的二維點,二維點以沿X軸和Z軸分佈. 而Y軸則代表地形的高度,將這些數據作為網格渲染得到大概的地貌『地形圖』,將『灰度值』剩以『地圖比例』的高地形的高度值,較亮的灰度對應於較高的地形,較暗的灰度對應於較低的地形.

『高度值=灰度值*地圖尺寸比例因子』
『地圖頂點座標=二維點索引*地圖尺寸比例因子』

渲染地形時沿著Z軸方向每個二維點使用GL_TRIANGLE_STRIP繪畫相連的三角形,沿X軸正方向移動按Z字形路線模式來繪製,當達到行的令一端時就移到下一行用同樣的方法進行繪製,如此直至完成繪畫.對地形進行紋理映射,因為紋理是正方形,所以每四個點頂點指定一個紋理,由兩個三角形組成四邊形,每個四邊形對應一個紋理.

除地形圖外還有海平面掩蓋低窪地帶,海平面由四邊形和的高度值組成,再將『水紋理』應用於四邊形使得海水具有真實感.

繪畫紋理地形的C代碼:

void Draw_Terrain(TERRAIN_PTR terrain)

{

// 繪畫紋理地形

glBindTexture(GL_TEXTURE_2D, terrain->grass.ID);

// 紋理顏色與像素顏色相剩

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

for (int z = 0; z < terrain->width – 1; ++z)

{

glBegin(GL_TRIANGLE_STRIP);// 繪畫三角形

for (int x = 0; x < terrain->width; ++x)

{// 一次渲染兩個頂點

float currScaledHeight = terrain->data[z * terrain->width + x] / terrain->scale;

float nextScaledHeight = terrain->data[(z + 1)* terrain->width + x] / terrain->scale;

float color = 0.5f + 0.5f * currScaledHeight / terrain->max_height; // 灰度值

float nextColor = 0.5f + 0.5f * nextScaledHeight / terrain->max_height; // 灰度值

glColor3f(color, color, color);

glTexCoord2f((GLfloat)x / terrain->width * 8.0f, (GLfloat)z / terrain->width * 8.0f);

glVertex3f((GLfloat)(x – terrain->width/2.0f), currScaledHeight,  (GLfloat)(z – terrain->width / 2.0f));

glColor3f(nextColor, nextColor, nextColor);

glTexCoord2f((GLfloat)x / terrain->width * 8.0f, (GLfloat)(z + 1.0f) / terrain->width * 8.0f);

glVertex3f((GLfloat)(x – terrain->width/2.0f), nextScaledHeight, (GLfloat)(z + 1.0f – terrain->width/2.0f));

}

glEnd();

}

// 繪畫水面

glBindTexture(GL_TEXTURE_2D, terrain->water.ID);// 綁定紋理

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);// 重複的紋理

glBegin(GL_QUADS);

glTexCoord2f(0.0f, 0.0f);// 紋理座標

glVertex3f(-terrain->width / 2.1f, terrain->water_height, terrain->width / 2.1f);// 頂點座標

glTexCoord2f(terrain->width / 4.0f, 0.0f);

glVertex3f(terrain->width / 2.1f, terrain->water_height, terrain->width / 2.1f);

glTexCoord2f(terrain->width / 4.0f, terrain->width / 4.0f);

glVertex3f(terrain->width / 2.1f, terrain->water_height, -terrain->width / 2.1f);

glTexCoord2f(0.0f, terrain->width / 4.0f);

glVertex3f(-terrain->width / 2.1f, terrain->water_height, -terrain->width / 2.1f);

glEnd();

}

演示程式:下載

  1. 鼠標『左/右』鍵移動相機繞Y軸旋轉
  2. 鼠標『上/下』鍵移動相機繞X軸旋轉

OpenGL之天幕

OpenGL之天幕

『天幕』其是就在一个大立方体的内侧贴上图像,从而绘画出远景地屏线效果,用于增加远景真实感有效而简单的方法,天幕的中心位于『相机』当前位置,所以当『相机』移动时『天幕』的中心点也同时移动.

演示程式:下载

  1. 按『左/右』键观察『前、后、左、右』的效果
  2. 按『上/下』键观察『天、地』的效果

『天幕』的算法

  1. 准备六张照片分别为『天、地、前、后、左、右』并载入『记忆体』
  2. 绘画一个大『正方体』由六个四边形组成
  3. 在『正方体』的内则贴上图像
  4. 『天幕』中心点与『相机』位置同步移动

 

渲染天幕C代码

void Render_SKYBOX(SKYBOX_PTR skybox,float xPos,float yPos,float zPos)

{

glPushMatrix();// 当前矩阵堆栈压栈

glTranslatef(xPos, yPos, zPos);// 移动相机位置

glPushAttrib(GL_FOG_BIT | GL_DEPTH_BUFFER_BIT | GL_LIGHTING_BIT);// 压入当前属性

glDisable(GL_DEPTH_TEST);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);// 设定纹理复盖模式为”重复纹理”

// 面紋理座標和頂點座標

// 天

glBindTexture(GL_TEXTURE_2D, skybox->texture[SKY_TOP].ID);// 绑定纹理

glBegin(GL_QUADS);

glTexCoord2f(1.0f, 1.0f); glVertex3f(-skybox->size, skybox->size, -skybox->size);

glTexCoord2f(0.0f, 1.0f); glVertex3f(skybox->size, skybox->size, -skybox->size);

glTexCoord2f(0.0f, 0.0f); glVertex3f(skybox->size, skybox->size, skybox->size);

glTexCoord2f(1.0f, 0.0f); glVertex3f(-skybox->size, skybox->size, skybox->size);

glEnd();

// 地

glBindTexture(GL_TEXTURE_2D, skybox->texture[SKY_BOTTOM].ID);

glBegin(GL_QUADS);

glTexCoord2f(1.0f, 1.0f); glVertex3f(skybox->size, -skybox->size, -skybox->size);

glTexCoord2f(0.0f, 1.0f); glVertex3f(-skybox->size, -skybox->size, -skybox->size);

glTexCoord2f(0.0f, 0.0f); glVertex3f(-skybox->size, -skybox->size, skybox->size);

glTexCoord2f(1.0f, 0.0f); glVertex3f(skybox->size, -skybox->size, skybox->size);

glEnd();

// 前

glBindTexture(GL_TEXTURE_2D, skybox->texture[SKY_FRONT].ID);

glBegin(GL_QUADS);

glTexCoord2f(0.0f, 0.0f); glVertex3f(-skybox->size, -skybox->size, -skybox->size);

glTexCoord2f(1.0f, 0.0f); glVertex3f(skybox->size, -skybox->size, -skybox->size);

glTexCoord2f(1.0f, 1.0f); glVertex3f(skybox->size, skybox->size, -skybox->size);

glTexCoord2f(0.0f, 1.0f); glVertex3f(-skybox->size, skybox->size, -skybox->size);

glEnd();

// 后

glBindTexture(GL_TEXTURE_2D, skybox->texture[SKY_BACK].ID);

glBegin(GL_QUADS);

glTexCoord2f(0.0f, 0.0f); glVertex3f(skybox->size, -skybox->size, skybox->size);

glTexCoord2f(1.0f, 0.0f); glVertex3f(-skybox->size, -skybox->size, skybox->size);

glTexCoord2f(1.0f, 1.0f); glVertex3f(-skybox->size, skybox->size, skybox->size);

glTexCoord2f(0.0f, 1.0f); glVertex3f(skybox->size, skybox->size, skybox->size);

glEnd();

// 右

glBindTexture(GL_TEXTURE_2D, skybox->texture[SKY_RIGHT].ID);

glBegin(GL_QUADS);

glTexCoord2f(1.0f, 0.0f); glVertex3f(skybox->size, -skybox->size, skybox->size);

glTexCoord2f(1.0f, 1.0f); glVertex3f(skybox->size, skybox->size, skybox->size);

glTexCoord2f(0.0f, 1.0f); glVertex3f(skybox->size, skybox->size, -skybox->size);

glTexCoord2f(0.0f, 0.0f); glVertex3f(skybox->size, -skybox->size, -skybox->size);

glEnd();

// 左

glBindTexture(GL_TEXTURE_2D, skybox->texture[SKY_LEFT].ID);

glBegin(GL_QUADS);

glTexCoord2f(1.0f, 0.0f); glVertex3f(-skybox->size, -skybox->size, -skybox->size);

glTexCoord2f(1.0f, 1.0f); glVertex3f(-skybox->size, skybox->size, -skybox->size);

glTexCoord2f(0.0f, 1.0f); glVertex3f(-skybox->size, skybox->size, skybox->size);

glTexCoord2f(0.0f, 0.0f); glVertex3f(-skybox->size, -skybox->size, skybox->size);

glEnd();

glPopAttrib();// 弹出当前属性

glEndList();

glPopMatrix();// 当前矩阵堆栈出栈

}

OpenGL之旗幟飄揚

OpenGL之旗幟飄揚

讓旗幟飄揚的核心是波浪算法,使用sin()函式將旗幟頂點初此化為波紋,然後每幀移動波紋

演示程式:下載

  1. 按方向鍵移動相機
  2. 按ESC鍵相機返回原點

算法如下:

  1. 將旗幟定義為長方形,橫向(x軸)36個頂點,縱向(y軸)20個頂點,35*19個網格
  2. 波紋算法: z = sin((x * height * 360) * 2 * π)
  3. 每幀沿Z軸往右移動波紋來模擬波浪運動,最右端的Z座標移動到最左端
  4. 在繪畫旗幟時從左下角開此,一次繪畫一個GL_QUAD按逆時針繪畫紋理座標與頂點座標
  5. 紋理座標:『s=x/width』『t=y/height』
  6. 旗幟『紋理』定義為正方形,分辨率越大越好,『紋理載入
旗幟結構 簡介
typedef struct FLAG_TAG{
float       points[36][20][3]; 頂點數據36*20個頂點,每個頂點3(xyz)個分量
int         time_start; 啟動時間用於控制波浪移動速度
}FLAG, *FLAG_PTR;

 

初此化旗幟使用sin()波紋函式來初此化旗幟

bool Init_Flag(FLAG_PTR flag)

{

if (flag == NULL)

return false;

for (int x = 0; x < 36; ++x)

{

for (int y = 0; y < 20; ++y)

{

flag->points[x][y][0] = (float)x;// X軸

flag->points[x][y][1] = (float)y;// Y軸

float value = (x*20.0f / 360.0f) * 2.0f * 3.14159f;

flag->points[x][y][2] = (float)sin(value);// 正弦計算

}

}

return true;

}

繪畫旗幟

void Draw_Flag(FLAG_PTR flag,float xPos,float yPos,float zPos,float xRot,float yRot,float zRot)

{

int x, y;

float left, right, top, bottom;

glPushMatrix();// 當前矩陣堆棧壓棧

glBindTexture(GL_TEXTURE_2D, Flag_Texture.ID);// 綁定紋理

glTranslatef(xPos, yPos, zPos);// 移動旗幟座標

glRotatef(xRot, 1.0f, 0.0f, 0.0f); // 繞X軸旋轉旗幟

glRotatef(yRot, 0.0f, 1.0f, 0.0f); // 繞Y軸旋轉旗幟

glRotatef(zRot, 0.0f, 0.0f, 1.0f); // 繞Z軸旋轉旗幟

glBegin(GL_QUADS);// 繪畫木箱頂面紋理座標和頂點座標

// 遍歷旗幟所有頂點,除了方向上的最後兩個點

// 因為只是用它來繪製每個方向上最後的GL_QUAD

for (x = 0; x < 35; ++x)

{

for (y = 0; y < 18; ++y)

{   // 為當前的四邊形計算紋理座標

left = (float)x / 35.0f;  //四邊形左則的紋理座標

bottom = (float)y / 18.0f ;//四邊形頂則的紋理座標

right = (float)(x+1) / 35.0f; //四邊形右則的紋理座標

top = (float)(y+1) / 18.0f ;   //四邊形底則的紋理座標

// 設定四邊形左下角的紋理座標與頂點座標

glTexCoord2f(left, bottom);// 紋理座標

glVertex3f(flag->points[x][y][0],

flag->points[x][y][1],

flag->points[x][y][2]);//頂點座標

// 設定四邊形右下角的紋理座標與頂點座標

glTexCoord2f(right, bottom);// 紋理座標

glVertex3f(flag->points[x+1][y][0],

flag->points[x+1][y][1],

flag->points[x+1][y][2]);//頂點座標

// 設定四邊形右上角的紋理座標與頂點座標

glTexCoord2f(right, top);// 紋理座標

glVertex3f(flag->points[x+1][y+1][0],

flag->points[x+1][y+1][1],

flag->points[x+1][y+1][2]);//頂點座標

// 設定四邊形左上角的紋理座標與頂點座標

glTexCoord2f(left, top);// 紋理座標

glVertex3f(flag->points[x][y+1][0],

flag->points[x][y+1][1],

flag->points[x][y+1][2]);//頂點座標

}

}

glEnd();

DWORD tick = GetTickCount(); //返回從操作系統啟動所經過的毫秒數

if ((tick – flag->time_start) > 100)

{

flag->time_start = tick;

float wrap;

// 生成旗幟的運動

// 訪問旗幟中的每一點,將每點的Z軸座標向右移動一位來模擬波浪運動

for (y = 0; y < 19; ++y)// Y軸方向循環

{// 存儲此行中最右端頂點的Z座標

wrap = flag->points[35][y][2];

for (x = 35; x >= 0; –x)// X軸方向循環

{// 將當前頂點Z座標設為前一頂點的Z座標值

flag->points[x][y][2] = flag->points[x-1][y][2];

}

// 將最左端頂點的Z座標設為先前所存儲的wrap

flag->points[0][y][2] = wrap;

}

}

glPopMatrix();// 當前矩陣堆棧出棧

}

 

OpenGL之紋理映射使用mipmap

OpenGL之紋理映射使用mipmap

紋理繪畫多邊形當遠離視點,會出現視覺失真或炫目問題,原因是OpenGL對兩個相鄰的像素進行采樣時,從紋理圖中的一些差別較大的部分進行采樣所產生的,在靜止場景問題並不明顯,若運動時紋理紋理采樣發生改變時炫目問題將會更特出,使用mipmap『紋理鏈』能消除部分失真,因為低解釋度的紋理被應用到遠距離的多邊形上時采樣更加精准.因為紋理一級級縮小時紋理可以保持平滑,使用mipmap『紋理鏈』的另一個好處是較小的紋理更容易保存在顯卡『記憶體』中提高命中率.

OpenGL的gluBuild2DMipmaps()可以全自動的生成mipmap『紋理鏈』.但不仿自已動手生成.

mipmap『紋理鏈』演示程式下載:

  1. 按M鍵可切換『紋理鏈』啟用與禁用,當啟用時炫目失真將大副減小.
  2. 按ESC鍵相機返回原點.
  3. 按方向鍵移動相機

紋理結構定義可梯『OpenGL之紋理映射』OpenGL根據目標圖像的大小選擇紋理圖像,『紋理鏈』索引從0開始到分辨率1*1 結束,所以你要對紋理近行縮小:

 

生成紋理鏈代碼

1.不斷縮小紋理圖,直到分辨率1*1

while (width != 1 && height != 1){

2.獲取索引

index = texture->count;

3.縮小紋理

texture->image[index] = Decrease_Image_Texture(texture->image[index-1], width, height);

4.紋理個數加一

++texture->count;

5.寬與高減一半

width = width / 2;

height = height / 2;

}

紋理圖像的寬和高均縮小一半的函式

image:紋理圖

width,height:寬和高

PBYTE Decrease_Image_Texture(PBYTE image,int width,int height){

int r1,r2,r3,r4, g1,g2,g3,g4, b1,b2,b3,b4 ;

int index,x,y;

//分配縮小紋理記憶體

buffer = (PBYTE)malloc(width/2 * height/2 * 3);

for (y = 0; y < height; y = y + 2) //遍歷Y座標

{

for (x = 0; x < width; x = x + 2)//遍歷X座標

{

index = Get_Index_Texture(x, y, 0, 0, width, height) * 3;// 提取紋理像素

r1 = image[index + 0];

g1 = image[index + 1];

b1 = image[index + 2];

index = Get_Index_Texture(x, y, 1, 0, width, height) * 3;// 提取紋理像素

r2 = image[index + 0];

g2 = image[index + 1];

b2 = image[index + 2];

index = Get_Index_Texture(x, y, 0, 1, width, height) * 3;// 提取紋理像素

r3 = image[index + 0];

g3 = image[index + 1];

b3 = image[index + 2];

index = Get_Index_Texture(x, y, 1, 1, width, height) * 3; //提取紋理像素

r4 = image[index + 0];

g4 = image[index + 1];

b4 = image[index + 2];

index = (y/2 * width/2 + x/2) * 3;

//加權平均計算目標紋理像素

buffer[index + 0] = (r1 + r2 + r3 + r4) / 4;

buffer[index + 1] = (g1 + g2 + g3 + g4) / 4;

buffer[index + 2] = (b1 + b2 + b3 + b4) / 4;

}

}

 

計算紋理像素索引函式

x,y:座標

dx,dy:座標增量

wdith,height:紋理圖的寬和高

int Get_Index_Texture(int x, int y, int dx, int dy, int width, int height) {

if (x + dx >= width) //判斷x座標是否越界

dx = 0;

if (y + dy >= height) //判斷y座標是否越界

dy = 0;

int index = (y + dy) * width + (x + dx);        計算紋理像素索引

return index;           返回索引

}

 

綁定mipmap『紋理鏈』代碼函式

bool Bind_Texture(TEXTURE_PTR texture){

glGenTextures(1, &texture->ID);//生成紋理

glBindTexture(GL_TEXTURE_2D, texture->ID);//綁定紋理

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);// 重複紋理

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);// 重複紋理

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);//放大紋理像素採樣線性插值(加權平均)

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);//縮小紋理紋理鏈採樣使用NEAREST,過濾使用LINEAR

for (int index = 0, v = 1; index < texture->count; ++index, v = v * 2)//遍歷紋理鏈

glTexImage2D(GL_TEXTURE_2D, index, GL_RGB, texture->width / v, texture->height / v, 0, GL_RGB, GL_UNSIGNED_BYTE, texture->image[index]);    //載入紋理

}

 

OpenGL之紋理映射

OpenGL之紋理映射

將紋理映射到3D模型是革命性技術,給人帶來照片般震撼逼真效果,簡單來講紋理映射就是將圖片附著於多邊形之上,這樣的圖片稱之為紋理,你可以將平鋪的地圖映射到球體上從而得到3D地球模型,下面以渲染木箱為例的演示程式:下載

生成紋理對像 簡介
void glGenTextures(GLsizei n,GLuint *textures); 生成紋理並返回紋理『索引』即ID編號
n 紋理個數
textures 數組,返回紋理ID

 

綁定紋理 簡介
void glBindTexture(GLenum target,GLuint texture); 生成紋理之後要進行綁定
Target GL_TEXTURE_1D:1維紋理

GL_TEXTURE_2D:2維紋理

Textures 紋理ID數組

 

過濾紋理 簡介
void glTexParameteri(GLenum target,GLenum pname,GLint param); 綁定之後要設定紋理過濾
target: GL_TEXTURE_1D:1維紋理

GL_TEXTURE_2D:2維紋理

pname: GL_TEXTURE_MIN_FILTER:縮小過濾

GL_TEXTURE_MAG_FILTER:放大過濾

GL_TEXTURE_WRAP_S:紋理S座標

GL_TEXTURE_WRAP_T:紋理T座標

param:

 

GL_REPEAT:重複(平鋪)紋理

GL_CLAMP:夾持紋理

GL_LINEAR:像素採樣線性插值(加權平均)

GL_NEAREST:像素採樣最接近中心紋理

GL_NEAREST_MIPMAP_NEAREST:紋理鏈採樣使用NEAREST,過濾使用NEAREST

GL_NEAREST_MIPMAP_LINEAR:紋理鏈採樣使用NEAREST,過濾使用LINEAR

GL_LINEAR_MIPMAP_NEAREST:紋理鏈採樣使用LINEAR,過濾使用NEAREST

GL_LINEAR_MIPMAP_LINEAR:紋理鏈採樣使用LINEAR,過濾使用LINEAR

 

載入紋理 簡介
void glTexImage2D(GLenum target,GLint   level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLint format,GLenum  type,const GLvoid *pixels); 設定紋理過濾後需要把紋理載入OpenGL

type:最常用GL_UNSIGNED_BYTE(無符號8Bit)

pixels:紋理數據

target: GL_TEXTURE_1D:1維紋理

GL_TEXTURE_2D:2維紋理

level: 紋理鏈索引,若只有單個紋理則設為0
internalformat: 最常用GL_RGBA或GL_RGB
width: 紋理寬度
height: 紋理高度
border: 紋理是否有變框,0沒有邊框,1有邊框
format: 最常用GL_RGBA或GL_RGB

 

紋理座標與頂點座標 簡介
void glTexCoord2f (GLfloat s, GLfloat t); 設定紋理座標(s,t), s軸紋理的x座標,t軸為紋理的y座標,紋理座標必需在頂點座標之前設定
void glVertex3f(GLfloat x,GLfloat y,GLfloat z); 設定頂點座標,並與紋理座標匹配

 

定義紋理結構 簡介
typedef struct TEXTURE_TYP{ 此結構用於保存紋理位圖信息
int   width; 紋理寬度
int   height; 紋理高度
int   bitCount; 位圖像素的bits (8BIT,16BIT,24BIT,32BIT)
int   size; 紋理數據的大小
PALETTEENTRY paletteentry; 位圖調色板
GLuint          ID; 紋理ID
PBYTE images[32]; mipmap紋理鏈
int   count; 紋理鏈個數
}TEXTURE, *TEXTURE_PTR;

 

 

紋理映射代碼示例

1.啟用深度緩衝測試,可保證多邊形被正確繪製

glEnable(GL_DEPTH_TEST);

2.啟動漸變效果

glShadeModel(GL_SMOOTH);

3.啟動多邊形隱面裁剪(消除隱藏面)如果要穿越實體則無需啟動

glEnable(GL_CULL_FACE);

4.設背面為隱面

glCullFace(GL_BACK);

5.多邊形正面使用逆時針

glFrontFace(GL_CCW);

6.啟用2D紋理映射

glEnable(GL_TEXTURE_2D);

7.載入位圖紋理(.bmp圖檔)( .tga圖檔)

TEXTURE texture;

Load_File_Texture(&texture,path);

8.生成1個紋理

glGenTextures(1, &texture->ID);

9.綁定紋理

glBindTexture(GL_TEXTURE_2D, texture->ID);

10.放大紋理像素採樣最接近中心紋理

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

11.縮小紋理過濾像素採樣最接近中心紋理

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

12.載入紋理

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture->width, texture->height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture->image[0]);

 

從指定的磁盤路徑載入紋理函式

bool Load_File_Texture(TEXTURE_PTR texture,const char * path)

{

char drive[_MAX_DRIVE] = { 0 };// 驅動器盤符

char dir[_MAX_DIR] = { 0 };    // 目錄

char fname[_MAX_FNAME] = { 0 };// 文件名

char ext[_MAX_EXT] = { 0 };    // 擴展名!

BITMAP_FILE bitmap;

TARGA_FILE  targa;

PCX         pcx;

if (texture == NULL || path == NULL)

return false;

//將路徑名分拆為組件!

_splitpath(path, drive, dir, fname, ext);

if (stricmp(ext, “.bmp”) == 0)// 載入位圖

{

Load_Bitmap(&bitmap, path);// 載入BMP文檔

Load_Bitmap_Texture(texture, &bitmap);// 載入紋理

}

else

if (stricmp(ext, “.tga”) == 0)// 載入位圖

{

Load_Targa(&targa, path); // 載入tga文檔

Load_Targa_Texture(texture, &targa);// 載入紋理

}

else

if (stricmp(ext, “.pcx”) == 0)// 載入位圖

{

Load_PCX(&pcx, path); // 載入PCX文檔

Load_PCX_Texture(texture, &pcx);// 載入紋理

}

return false;

}

激活紋理

void Bind_Texture(TEXTURE_PTR texture){

glEnable(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, texture->ID);// 綁定紋理

}

 

Windows10輸入『』

Windows10輸入『』

「」與『』符號在標準的英語鍵盤中你是穩唔到這些按鍵,但可按以下方法輸入:

  1. 按CTRL+SHIFT切換到『微軟注音輸入法』
  2. 鼠標右鍵按『中/英』彈出菜單
  3. 按『輸入法整合器』
  4. 按『符』-『符號查詢『
  5. 『符號類別』選『標點符號』
  6. 選擇你想要的符號

如果在WORD可使用快捷鍵輸入,按住ALT鍵不放然後再按數字鍵,是唔是好方便呢.

字符 快捷鍵
ALT鍵+12302鍵
ALT鍵+12303鍵
ALT鍵+12300鍵
ALT鍵+12301鍵

 

 

Windows之重複的WM_COMMAND Message

Windows之重複的WM_COMMAND Message

近日將WinXP升為Win10,將VC6升為VS2016.按Menu後在WindowProc()會接收到兩個重複的WM_COMMAND Message.而Accelerator更會接收多個WM_COMMAND Message.同樣的代碼在WinXP和VC6重未出現.不斷查看Winmain()事件循環.因為遊戲引擎是實時驅動而非消息驅動的.所以使用PeekMessage ()而非GetMessage()讀取消Message.當改為while(GetMessage (&msg, NULL, 0, 0))消息驅動後問題無在出現.梯來是MSG這個Message沒有被清空道至.調用memset(&msg, 0, sizeof(MSG)); 問題得到完美解決.

主事件循環代碼簡介

1.WINDOWS消息的存儲器

MSG msg;

2.Accelerator加速鍵表的句柄

HACCEL hAccel;

hAccel =::LoadAccelerators(main_instance,”ACCEL”);

2.主事件循環非消息驅動的

while(true) {

3.清空MSG

memset(&msg, 0, sizeof(MSG));

4.從事件對列中獲得消息

PeekMessage(&msg,NULL,0,0,PM_REMOVE);

5.由 PostQuitMessage(0) 發送的WM_QUIT消息,被PeekMessage()檢測到跳出主循環

if(msg.message == WM_QUIT)

break;

6.處理加速鍵表

if(!::TranslateAccelerator(main_window,hAccel,&msg)) {

7.處理和轉換加速鍵.

TranslateMessage(&msg);

3.調用WinProc對消息進行處理,從MSG結構取的參數並傳遞.

DispatchMessage(&msg);

}

}

OpenGL之讀取Targa圖檔-RLE解碼

OpenGL之讀取Targa圖檔-RLE解碼

『Targa』與『Bitmap』同樣支持RLE編碼,單編碼方式有點不同.而且『索引、RGB、灰度』均支持RLE編碼.RLE編碼無非兩種方式『重複』與『不重複』的像素.渲染演示程式下載:

讀取ID 簡介
if(ID>=128)

Len = (BYTE)(ID – 127);

重複像素

LEN像素量

if(ID<128)

Len = BYTE(ID + 1);

不重複的像素

LEN=像素量

RLE解碼的C代碼

image:輸出

data:輸入RLE圖像數據

image_size:image圖像數據長度

pixel_size:像素大細

void Load_RLE_Targa(PBYTE image, PBYTE data, int image_size,int pixel_size)

{

BYTE id;//重複像素ID>=128,不重複的像素ID<128

BYTE length; //像素個數

BYTE pixel[4] = {0,0,0,0};// 像素

int image_index = 0;//圖像索引

int data_index = 0;//RLE索引

while (image_index < image_size)

{

id = data[data_index++];// 讀取ID

if (id >= 128)// 重複的像素

{   // 像素個數

length = (BYTE)(id – 127);//像素個數

memcpy(pixel, &data[data_index], pixel_size); // 讀重複像素

data_index = data_index + pixel_size;//移動RLE索引

while (length > 0)//  重複寫入數據

{

memcpy(image+image_index, pixel, pixel_size);//重複寫入數據

image_index = image_index + pixel_size;//移動圖像索引

–length;// 個數減一

}

}

else

{  // 不重複的像素

length = BYTE(id + 1); // 像素個數

// 拷貝像素

memcpy(image+image_index, data+data_index, length*pixel_size);

image_index = image_index + length * pixel_size;// 移動圖像索引

data_index = data_index + length * pixel_size; //移動RLE索引

}

}

}

OpenGL之讀取Targa圖檔

OpenGL之讀取Targa圖檔

『Targa』是常用於3D紋理的『.tga』圖檔,它與『Bitmap』最大的分別是索引、RGB、灰度均支持RLE編碼,當色彩較單調時壓縮效果明顯. 渲染演示程式下載:

它的文檔結構主要由三部份組成:

Targa圖檔結構 簡介
HEADER header; 頭部
PALETTEENTRY palette[256]; 調色板常用於256色模式,灰度模式和RGB模式均無調色板
PBYTE buffer; 位圖數據

 

頭部結構 簡介
BYTE imageIDLength; 圖像頭部的長度
BYTE colorMayType 調色板類型

0=無

1=使用調色盤

BYTE imageTypeCode 圖像類型

0=無圖像數據

1=索引模式

2= RGB模式

3=灰度模式

9=RLE壓縮索引模式

10=RLE壓縮RGB模式

11=RLE壓縮灰度模式

WORD colorMapOrigin 調色板偏移量
WORD colorMapLength 調色板的長度8bit圖檔這個值為256
BYTE colorMapEntrySize 調色板單個條目的大細

有本書居然寫錯左所占空間大細暈

WORD imageXOrigin 圖像左下角的X軸座標總為0
WORD imageYOrigin 圖像左下角的Y軸座標總為0
WORD imageWidth 圖寬
WORD imageHeight 圖高
BYTE bitCount 像素8BIT,16BIT,24BIT,32BIT
BYTE imageDescriptor 圖像原點的位置

 

調色板結構 簡介
BYTE red; 紅色
BYTE green; 綠色
BYTE blue; 藍色

 

載入並分釋TARGA圖檔

bool Load_Targa(TARGA_FILE_PTR targa, PBYTE data,int size)

{

int index;

PBYTE image;

int   image_size;// 圖像字節的長度

int   pixel_size;// 像素大小

int   pixel_count;// 像素個數(寬*高)

memcpy(&targa->header, data, sizeof(TARGA_HEADER));// 讀取頭部數據

image_size = targa->header.imageWidth * targa->header.imageHeight * targa->header.bitCount / 8;

pixel_size = targa->header.bitCount / 8;

pixel_count = targa->header.imageWidth * targa->header.imageHeight;

targa->buffer = (PBYTE)malloc(image_size);// 根據位圖影像的大小申請空間

if (targa->buffer == NULL)

return false;//出錯返回

if (targa->header.imageTypeCode == TARGA_TYPE_INDEXED ||

targa->header.imageTypeCode == TARGA_TYPE_INDEXED_RLE )// 壓縮索引

image = data + sizeof(TARGA_HEADER) + targa->header.imageIDLength + targa->header.colorMapOrigin + (targa->header.colorMapEntrySize / 8) * targa->header.colorMapLength;

else

image = data + sizeof(TARGA_HEADER) + targa->header.imageIDLength ;

if( targa->header.imageTypeCode == TARGA_TYPE_INDEXED ||// 索引

targa->header.imageTypeCode == TARGA_TYPE_RGB     ||// RGB

targa->header.imageTypeCode == TARGA_TYPE_GRAYSCALE)// 灰度

{   // 讀取位圖的圖像

memcpy(targa->buffer, image, image_size);

}

else

if (targa->header.imageTypeCode == TARGA_TYPE_INDEXED_RLE  ||// 壓縮索引

targa->header.imageTypeCode == TARGA_TYPE_RGB_RLE      ||// 壓縮RGB

targa->header.imageTypeCode == TARGA_TYPE_GRAYSCALE_RLE )// 壓縮灰度

{ // RLE解碼

Load_RLE_Targa(targa->buffer, image, image_size, pixel_size);

}

if (targa->header.bitCount == 8)

{   // 計算調色板的入口地址

PBYTE  palette = data + sizeof(TARGA_HEADER) + targa->header.imageIDLength + targa->header.colorMapOrigin;

// RGBQUAD結構與PALETTEENTRY結構的順序調轉了

for (index = 0; index < targa->header.colorMapLength; index++)

{//掉轉調色板的紅色和綠色

targa->palette[index].red   = palette[index *targa->header.colorMapEntrySize/8 + 2];

targa->palette[index].green = palette[index *targa->header.colorMapEntrySize/8 + 1];

targa->palette[index].blue  = palette[index *targa->header.colorMapEntrySize/8 + 0];

targa->palette[index].flags = PC_NOCOLLAPSE;

}

PBYTE temp_buffer = targa->buffer;

//根據圖像的寬高計算記憶體空間(24BIT)

targa->buffer = (UCHAR *)malloc(targa->header.imageWidth * targa->header.imageHeight * 3);

if (targa->buffer == NULL)

return false;//出錯返回

for (index = 0; index < image_size; index++)

{ // 現在將索引值轉為24位值

int color = temp_buffer[index];

if (targa->header.imageTypeCode == TARGA_TYPE_GRAYSCALE ||

targa->header.imageTypeCode == TARGA_TYPE_GRAYSCALE_RLE)

{// 處理灰度圖像

targa->buffer[index * 3 + 0] = color;

targa->buffer[index * 3 + 1] = color;

targa->buffer[index * 3 + 2] = color;

}

else

{

targa->buffer[index * 3 + 0] = targa->palette[color].red;

targa->buffer[index * 3 + 1] = targa->palette[color].green;

targa->buffer[index * 3 + 2] = targa->palette[color].blue;

}

}

targa->header.bitCount = 24;//最後將位圖位數變為24位

}

else

if (targa->header.bitCount == 16)//RGB555

{   // 根據位圖影像的大小申請空間

PBYTE temp_buffer = targa->buffer;

// 根據位圖影像的大小生請空間(位圖為16位但要生成24位空間來保存)

targa->buffer = (UCHAR *)malloc(targa->header.imageWidth * targa->header.imageHeight * 3);

if (targa->buffer == NULL)

{//分配內存空間失敗

free(temp_buffer); // 釋放資源

return false;//出錯返回

}

for (index = 0; index < pixel_count; ++index)

{

WORD color = (temp_buffer[index2 + 1] << 8) | temp_buffer[index2 + 0];

UCHAR red = (((color) >> 10) & 0x1f);

UCHAR green = (((color) >> 5) & 0x1f);

UCHAR blue = ((color) & 0x1f);

targa->buffer[index * 3 + 0] = (red << 3);

targa->buffer[index * 3 + 1] = (green << 3);

targa->buffer[index * 3 + 2] = (blue << 3);

}

targa->header.bitCount = 24;//最後將位圖位數變為24位

free(temp_buffer); // 釋放資源

}

else

if (targa->header.bitCount == 24)

{

for (index = 0; index < image_size; index = index + 3)

{

UCHAR blue = targa->buffer[index + 0];

UCHAR green = targa->buffer[index + 1];

UCHAR red = targa->buffer[index + 2];

targa->buffer[index + 0] = red ;

targa->buffer[index + 2] = blue;

}

}

else

if (targa->header.bitCount == 32)

{

for (index = 0; index < image_size; index = index + 4)

{

//DWORD color;//32的顏色

UCHAR blue = targa->buffer[index + 0];

UCHAR green = targa->buffer[index + 1];

UCHAR red = targa->buffer[index + 2];

targa->buffer[index + 0] = red;

targa->buffer[index + 2] = blue;

}

}

// 判斷圖像原點是否左下角,否則翻轉圖像

if ((targa->header.imageDescriptor & TARGA_ORIGIN_TOP_LEFT) == TARGA_ORIGIN_TOP_LEFT)

Flip_Targa(targa->buffer, targa->header.imageWidth * pixel_size, targa->header.imageHeight);

return true;//

}

 

將顛倒的圖像翻轉過來

image:指向位圖數據

bytes_per_line:圖像每行所占的字節數

height:圖像的高度

bool Flip_Targa(UCHAR *image, int bytes_per_line, int height)

{

UCHAR *buffer; //用於臨時保存位圖數據.

int index;     //循環計數

//根據位圖影像的大小生請空間

buffer = (UCHAR )malloc(bytes_per_lineheight);

if (buffer == NULL)

return false;

// 位圖拷貝

memcpy(buffer, image, bytes_per_line*height);

// 垂直顛倒圖片

for (index = 0; index < height; index++)

memcpy(&image[((height – 1) – index)bytes_per_line], &buffer[indexbytes_per_line], bytes_per_line);

//釋放臨時空間

free(buffer);

return true;//返回

}

OpenGL之讀取Bitmap圖檔-RLE解碼

OpenGL之讀取Bitmap圖檔-RLE解碼

『Bitmap』若是8Bit圖檔則支持RLE編碼(run length encoding),但網絡上大多解釋器都不支持RLE解碼,實現它非常間單,但若顏色較多很可能壓縮後的尺寸比不壓縮之前還要大. Bitmap文檔的『compression』等於1則使用RLE8編碼: 渲染演示程式下載:

數值 簡介
00 00 本行結尾,座標移至下一行頭部
00 01 位圖結束完成解碼
00 02 x y 第三第四字節分別當前位置的X與Y偏移量
00 len val val val 00 非壓縮不重複數據,此數值長度要以2對齊,不足以0補齊

若數值為:00 03 BB CC DD 00

則解壓後:BB CC DD

len val 壓縮的重複數據

若數值為:04 88

則解壓後:88 88 88 88

BMP-8Bit模式的RLE解碼

image:輸出

data:輸入RLE圖像數據

data_size:RLE圖像數據長度

void Load_RLE8_Bitmap(PBYTE image, PBYTE data, int data_size, int width)

{

BYTE value;

BYTE length;// 像素個數

int image_index = 0;

int data_index = 0;

int x = 0;

int y = 0;

while (data_index < data_size)// 遍歷壓縮後數據

{

if (data[data_index] == 0 && data[data_index + 1] == 0)

{// 本行結尾

data_index = data_index + 2;

x = 0;

++y;

}

else

if (data[data_index] == 0 && data[data_index + 1] == 1)

{// 位圖結尾

data_index = data_index + 2;

return ;

}

else

if (data[data_index] == 0 && data[data_index + 1] == 2)

{// 當前位置的偏移

x = x + data[data_index + 2];

y = y + data[data_index + 3];

data_index = data_index + 4;

}

else

if (data[data_index] == 0)

{// 非壓縮不重複數據

length = data[data_index+1];

image_index = y * width + x;

memcpy(image + image_index, data+data_index+2, length);

x = x + length;

data_index = data_index + length + 2 + length%2;

}

else

if(data[data_index] > 0)

{// 壓縮的重複數據

length = data[data_index];

value = data[data_index + 1];

image_index = y * width + x;

memset(image + image_index, value, length);

x = x + length;

data_index = data_index + 2;// 重複的像素

}

}

}

OpenGL之讀取Bitmap圖檔

OpenGL之讀取Bitmap圖檔

『Bitmap』圖檔之副檔名使用『.bmp』它非常簡單易讀,記得在2005年學DirextX時寫圖檔分析器就是它.缺點不支持壓縮.8Bit(256色)支持RLF壓縮但只有色彩單調時才有效果否則文檔更大. 不要以為256色已經淘汰,通過更換調色板的顏色可以快速更換顏色依然大有用處.渲染演示程式下載:

BMP文檔由四部分組成:

『Bitmap』文檔結構 簡介
FILE_HEADER    file; 圖檔的頭部
INFO_HEADER   info; 圖檔的信息
PALETTEENTRY  palette[256]; 調色板只用於256色.

16Bit、24Bit、32Bit均無調色板

PBYTE         buffer; 圖像數據

要在OpenGL中渲染像素『Pixel』要倒轉排成RGB/RGBA順序

 

FILE_HEADER文檔結構 簡介
WORD  type; ‘MB’ 0x4d42 BMP文檔標記

用於判斷是否BMP文檔

DWORD size; 文檔大小,判斷文檔是否完整
WORD  reserved1; 保留
WORD  reserved2; 保留
DWORD OffBits; 圖像數據的偏移量(文檔的頭部)

 

INFO_HEADER圖檔信息頭部 簡介
DWORD size; 圖檔信息頭部的大小
LONG  width; 圖檔寬度像素『Pixel』
LONG  height; 圖檔高度像素『Pixel』
WORD  planes; 平面量,總為1
WORD  bitCount; 位圖像素尺寸:

8Bit(256色)支持RLF壓縮

16BIT(分為RGB555與RGB565), 24BIT, 32BIT

DWORD compression; 壓縮類型:

0 = RGB

0 = RGB555 0x0RRRRRGGGGGBBBBB

3 = RGB565 0xRRRRRGGGGGGBBBBB

1 = RLE8 (run length encoding)壓縮

2 = RLE4

DWORD sizeImage; 圖檔數據所占空間,若使用RLE壓縮為壓縮後的大細
LONG  XPelsPerMeter; X軸每米像素
LONG  YPelsPerMeter; Y軸每米像素
DWORD ClrUsed; 圖像顏色量
DWORD ClrImportant; 圖像重要顏色量

 

PALETTEENTRY調色板 簡介
BYTE red; 紅色
BYTE green; 綠色
BYTE blue; 藍色
BYTE flags 只用於DirectDraw

PC_EXPLICIT:映射到硬件

PC_NOCOLLAPSE:不要映射

PC_RESERVED:保留

 

載入BMP位圖C代碼

bool Load_Bitmap(BITMAP_FILE_PTR bitmap,PBYTE data,int size)

{

int index;

int line_size;// 圖像每行所占的字節數

int pixel_size ;// 像素大小

PBYTE image;

int width ;// 圖寬

int height;// 圖高

// 讀取頭部數據

memcpy(&bitmap->header, data, sizeof(BITMAP_FILE_HEADER));

// 判斷是否是位圖文件

if (bitmap->header.type != BITMAP_ID)

return false;//出錯返回

// 讀取位圖信息的頭部

memcpy(&bitmap->info, data + sizeof(BITMAP_FILE_HEADER), sizeof(BITMAP_INFO_HEADER));

if (bitmap->info.sizeImage == 0)

{

bitmap->info.sizeImage = size – sizeof(BITMAP_FILE_HEADER) – sizeof(BITMAP_INFO_HEADER);

if (bitmap->info.bitCount == 8)

bitmap->info.sizeImage = bitmap->info.sizeImage – MAX_COLORS_PALETTE * sizeof(BITMAP_PALETTEENTRY);

}

//定位圖像數據

image = data + size – (int)bitmap->info.sizeImage;// 相對於文件尾

line_size = bitmap->info.sizeImage / bitmap->info.height;// 圖像每行所占的字節數

pixel_size = bitmap->info.bitCount / 8;// 像素大小

width = bitmap->info.width;// 圖寬

height = abs(bitmap->info.height);// 圖高

// 讀取位圖8或16,32位圖

if (bitmap->info.bitCount == 8)

{   // 讀取位圖的調色板

PBYTE palette = data + sizeof(BITMAP_FILE_HEADER) + sizeof(BITMAP_INFO_HEADER);

// RGBQUAD結構與PALETTEENTRY結構的順序調轉了

for (index = 0; index < MAX_COLORS_PALETTE; index++)

{//掉轉紅色和綠色

bitmap->palette[index].red   = palette[index * 4 + 2];

bitmap->palette[index].green = palette[index * 4 + 1];

bitmap->palette[index].blue  = palette[index * 4 + 0];

bitmap->palette[index].flags = PC_NOCOLLAPSE;

}

//根據位圖影像的大小生請空間

bitmap->buffer = (UCHAR *)malloc(abs(bitmap->info.width * bitmap->info.height * 3));

if (bitmap->buffer == NULL)

return false;//出錯返回

PBYTE buffer = NULL;

if (bitmap->info.compression == BITMAP_COMPRESSION_RLE8)

{

buffer = (PBYTE)malloc(abs(bitmap->info.width * bitmap->info.height));

Load_RLE8_Bitmap(buffer, image, bitmap->info.sizeImage, bitmap->info.width);// RLE解碼

image = buffer;

}

// 現在將索引值值轉為24BIT

for (int y = 0; y < height; ++y)

{

for (int x = 0; x < width; ++x)

{

index = y * width + x;

int color = image[index];

bitmap->buffer[index * 3 + 0] = bitmap->palette[color].red;

bitmap->buffer[index * 3 + 1] = bitmap->palette[color].green;

bitmap->buffer[index * 3 + 2] = bitmap->palette[color].blue;

}

}

if (bitmap->info.compression == BITMAP_COMPRESSION_RLE8)

free(buffer);

//最後將位圖位數變為24位

bitmap->info.bitCount = 24;

}

else

if (bitmap->info.bitCount == 16)// 讀取16位圖

{  // 以24BIT分配記憶體空間

bitmap->buffer = (UCHAR *)malloc(abs(bitmap->info.width * bitmap->info.height * 3));

if (bitmap->buffer == NULL)

return false;//出錯返回

if (bitmap->info.compression == 3)

{// RGB565

for (int y = 0; y < height; ++y)

{

for (int x = 0; x < width; ++x)

{// 現在將各個16位RGB值轉為32位值

index = y * line_size + x * 2;

WORD color = (image[index + 1] << 8) | image[index + 0];

UCHAR red = ((color >> 11) & 0x1f);

UCHAR green = ((color >> 5) & 0x3f);

UCHAR blue = (color & 0x1f);

index = y * width + x;

bitmap->buffer[index * 3 + 0] = (red << 3);

bitmap->buffer[index * 3 + 1] = (green << 2);

bitmap->buffer[index * 3 + 2] = (blue << 3);

}

}

}

else

{// RGB555

for (int y = 0; y < height; ++y)

{

for (int x = 0; x < width; ++x)

{

index = y * line_size + x * 2;

WORD color = (image[index + 1] << 8) | image[index + 0];

UCHAR red = (((color) >> 10) & 0x1f);

UCHAR green = (((color) >> 5) & 0x1f);

UCHAR blue = ((color) & 0x1f);

index = y * width + x;

bitmap->buffer[index * 3 + 0] = (red << 3);

bitmap->buffer[index * 3 + 1] = (green << 3);

bitmap->buffer[index * 3 + 2] = (blue << 3);

}

}

}

//最後將位16BIT變為24BIT

bitmap->info.bitCount = 24;

}

else

if (bitmap->info.bitCount == 24)// 讀取24BIT圖檔

{   // 根據位圖影像的大小申請空間

bitmap->buffer = (UCHAR *)malloc(bitmap->info.sizeImage);

if (bitmap->buffer == NULL)// 申請內存空間失敗

return false;//出錯返回

// 讀取圖像

for (int y = 0; y < height; ++y)

{

for (int x = 0; x < width; ++x)

{// 轉換GL_RGB模式

index = y * line_size + x * 3;

bitmap->buffer[index + 0] = image[index + 2];//逐個像素地拷貝

bitmap->buffer[index + 1] = image[index + 1];

bitmap->buffer[index + 2] = image[index + 0];

}

}

}

else

if (bitmap->info.bitCount == 32)// 處理32BIT圖檔

{       // 根據位圖影像的大小申請空間

bitmap->buffer = (UCHAR *)malloc(bitmap->info.sizeImage);

if (bitmap->buffer == NULL)//若不能申請空間

return false;//出錯退出

// 像素轉為BGRA 32Bit肯定是4字節對齊

for (index = 0; index < (int)bitmap->info.sizeImage-4; index=index+4)

{

bitmap->buffer[index + 0] = image[index + 2];//逐個像素地拷貝

bitmap->buffer[index + 1] = image[index + 1];

bitmap->buffer[index + 2] = image[index + 0];

bitmap->buffer[index + 3] = image[index + 3];

}

}

else

{

return false;//嚴重文提

}

if (bitmap->info.height < 0)// height為負時表示圖片顛倒

Flip_Bitmap(bitmap->buffer, bitmap->info.width*(bitmap->info.bitCount / 8), bitmap->info.height);

bitmap->info.height = abs(bitmap->info.height);

return true;

}

 

將顛倒的BMP文件翻轉過來

bool Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)

{

UCHAR *buffer; //用於臨時保存位圖數據.

int index;     //循環計數

//分配單行空間

buffer = (UCHAR )malloc(bytes_per_lineheight);

if (buffer == NULL)

return false;

// 單行拷貝

memcpy(buffer, image, bytes_per_line*height);

// 垂直顛倒圖片

for (index = 0; index < height; index++)

memcpy(&image[((height – 1) – index)bytes_per_line], &buffer[indexbytes_per_line], bytes_per_line);

//釋放空間

free(buffer);

return true;//返回

}

OpenGL之繪畫圖像文檔

OpenGL之繪畫圖像文檔

在屏幕上渲染圖檔與模型貼上紋理總會令人興奮,幸好在OpengGL繪畫圖像文檔也並不困難,並且實現左示例程式.下載:

  1. 載入並解釋圖像文檔如『.bmp』『.tga』『.pcx
  2. 設置圖像左下角繪畫在屏幕位置glRasterPos2f(x, y);
  3. 設置圖像的縮放比glPixelZoom(xfactor,yfactor);縮放因子=屏幕尺寸/圖像尺寸
  4. 繪畫圖像glDrawPixels(width,height,format,type,pixels);與『DirectDraw』相比稍複雜點, 『DirectDraw』支持32Bit、16Bit、256色.而OpenGL卻直接支持32Bit、24Bit、256色、但要將像素『Pixel』倒轉排成RGB/RGBA順序
Format 簡介
GL_RGB 24Bit
GL_RGBA 32Bit
GL_COLOR_INDEX 調色板索引

 

type 簡介
GL_UNSIGNED_BYTE 像素『Pixel』分量的尺寸
GL_BITMAP 點陣位圖1位『Bit』1像素『Pixel』

 

常見圖檔格式讀取與分析 RLE解碼
Bitmap文檔 8Bit的bitmap支持RLE編碼
Targa圖檔 索引模式、RGB模式、灰度模式均支持RLE編碼
PCX圖檔 8Bit的PCX支持RLE編碼
PNG圖檔

 

渲染位圖C代碼演示:

  1. glPixelStorei(GL_UNPACK_ALIGNMENT, 4);// 4字節對齊
  2. glRasterPos2f(x, y);// 設定圖像左下角在屏幕的位置
  3. glPixelZoom((float)screen_width/(float)image_width, (float)screen_height / (float)image_height); // 設置全屏縮放
  4. glDrawPixels(image_width,image_height,format,type,image); // 繪畫

Windows之ALT快捷鍵

Windows之ALT快捷鍵

之前一值無法使用ALT鍵,因查找唔到其VK_ALT對應的『VIRTUAL CODE』,近日把WinXP切底拋棄改用Win10,發現很多程式均使用ALT鍵展示或隱藏MENU. 細想VK_ALT即等於VK_MENU,下面是使用ALT鍵展示與隱藏MENU源代碼

1.在resource.h加入

#define IDALT                           1000

2.在resource.rc加入加速表,一定要加入ALT否則MENU會獲得焦點要按量下ALT鍵,另不要用VK_LMENU和VK_RMENU

ACCEL ACCELERATORS

BEGIN

VK_MENU,        IDALT,                  VIRTKEY, ALT, NOINVERT

END

3.在main()修改消息循環

MSG msg;//消息 msg是WINDOWS放置下一個消息的存儲器,

HACCEL hAccel; // 加速鍵表的句柄

hAccel =::LoadAccelerators(main_instance,”ACCEL”); // 加速鍵表的句柄

while(GetMessage(&msg,NULL,0,0)) //從事件對列中獲得消息

{  //由 PostQuitMessage(0) 發送的WM_QUIT消息,被PeekMessage()檢測到

if(msg.message == WM_QUIT)

break;// 跳出主循環

if(!::TranslateAccelerator(main_window,hAccel,&msg))// 處理加速鍵表

{

TranslateMessage(&msg);//處理和轉換加速鍵.

DispatchMessage(&msg);//調用WinProc對消息進行處理,從MSG結構取的參數並傳遞.

}

}

4.在WinProc加入

if(msg == WM_COMMAND)

{ // 處理菜單命令

if (LOWORD(wParam) == IDALT)

{     main_menu = ::LoadMenuA(NULL,”MAIN_MENU”);// 主菜單

if (::GetMenu(main_window) == NULL)

::SetMenu(main_window, main_menu);// 設定菜單

else

::SetMenu(main_window, NULL);// 設定菜單

}

}

Visual Studio 2017新增C專案

Visual Studio 2017新增C專案
Visual Studio 2017新增C專案

近日終於遠離最愛的VC6安裝VC2017,新增專案時居然無發現C/C++的選項,暈難道C已被拋棄?經一番鑽然才悟個中方法

  1. 運行Visual Studio 2017
  2. 『檔案/新增/專案』打開
  3. 『新增檔案/Visual C++/空白專案』
  4. 若無梯見請點按『開啟Visual Studio安裝程式』把與C++有關全部安裝
  5. 『名稱填』這裡填『OpenGL』
  6. 『位置填』這裡填『D:\C\』
  7. 取消勾選『為方案建目錄』單級目錄結構與VC6相若
  8. 按『確認』製作專案
  9. 右鍵點擊『OpenGL』打開屬性頁
  10. 打開『屬性頁/組態屬性/一般/字元集選則『使用Unicode字元集』.若選『使用多位元組字元集』則使用ANSI
  11. 打開『屬性頁/組態屬性/連接器/系統/子系統選則『Windows(/SUBSYSTEM:WINDOWS)』圖形界面。若選『主控台(/SUBSYSTEM:CONSOLE)』則為命令行界面
  12. 右鍵點擊『OpenGL』點擊『加入/新的篩選條件』填main
  13. 右鍵點擊『main』點擊『加入/新的篩選條件』
  14. 『名稱』填『main.c』副檔名為.c則使用C編譯器, 副檔名為.cpp則使用C++編譯器

 

 

OpenGL之點陣字體

OpenGL之點陣字體

在OpenGL輸出文字可用繪畫好的文本位圖,再繪畫上屏幕.也是遊戲製作通用手法.將基本ASCII文本存為16Bit*16Bit(32Byte)二進制點陣字體

指定位圖的繪畫位置

void glRasterPos2i(GLint x, GLint y);

繪畫位圖

void WINAPI glBitmap(

GLSizei width,         GLSizei height, ASCII文本的寬和高這裡均為16

GLfloat xorig,         GLfloat yorig,當前繪畫位置的偏移

GLfloat xmove,         GLfloat ymove, 下次繪畫位置的增量

const GLubyte *bitmap); 二進制點陣字體

以位畫字符B的函式為例:

  1. const unsigned char BITMAPFONT_B[] //16Bit * 16Bit 點陣字體={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x00,0x66,0x00,0x66,0x00,0x66,0x00, 0x66,0x00,0x7C,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0xFC,0x00,0x00,0x00,0x00,0x00};
  2. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);// 對齊像素字節
  3. glColor3f(1.0f, 1.0f, 1.0f);// 顏色
  4. glRasterPos2i(x, y);// 設定位圖的位置
  5. glBitmap(16, 16, 0, 0, 16, 0, BITMAPFONT_B);// 渲染字符B

點陣字體的程序示例:下載

  1. 把輸入法設為英文
  2. 通過WM_CHAR接收ASCII碼並在屏幕繪畫
  3. 在遊戲設計中此方法也適用漢字渲染,只要把漢字轉換為點陣字體

Windows10之切底禁用Update Assistant

Windows10之切底禁用Update Assistant

『Windows10 Update Assistant』又稱為『Windows 10 更新小幫手』會自動彈出下載並安裝更新.但更新後卻把我的『港版Win10』變為『台版Win10』更新時還不能保留原有程式.最煩的是經常自動彈出.即使卸載Uninstall後還是會自動安裝. 經一番研究只禁『Windows10 Update Assistant』自動彈出,而『Windows10 Update』仍在後臺自動更新系統

  1. 『檔案總管\控制台\所有控制項目\程式和功能\ Windows10 Update Assistant』按兩下進行卸載Uninstall
  2. 『檔案總管\控制台\所有控制台項目\系統管理工具\工作排程器』按兩下啟動
  3. 『工作排程器\工作排程器程式庫\Microsoft\Windows\UpdateOrchestrator』按兩下打開
  4. 分別將『UpdateAssistant』『UpdateAssistantCalendarRun』『UpdateAssistantWakeupRun』按右側『停用』鍵把狀態設為『已停用』

 

Windows10之徹底禁用Windows Defender

Windows10之徹底禁用Windows Defender

Windows Defender是Windows10內置免費的既時保護查找惡意程式,但它卻經常錯報誤報影響日常工作,而且暫用大量資源,需然可然暫時關閉既時保護.『設定/更新與安全性/Windows Defender/既時保護/關閉』但更新病毒資料庫後又會開啟,你需要停止系統服務

  1. WIN+R輸入並運行msc
  2. 『本機群組原則編輯器\電腦設定\系統管理範本\Windows元組\ Windows Defender』
  3. 按兩下『關閉Windows Defender防病毒軟體』
  4. 勾選『以啟用』按『確定』.Windows Defender則徹底禁用
  5. 若要啟用Windows Defender則勾選『尚未設定』

記憶體(RAM)之帶寬

記憶體(RAM)之帶寬
wmic memorychip

記憶體(RAM)容量對計算機性能起直接的影響,而另一個關鍵參數記憶體(RAM)帶寬(Bandwidth) ,帶寬越高與CPU之間交換數據更快,更有利提高計算機性能.

計算公式如下:

帶寬(Bandwidth)=工作頻率(DRAM Frequency)*位寬(DataWidth)

  公式 簡介
工作頻率Frequency 工作頻率=記憶體頻率*通道數量 相當於車速
位寬(DataWidth) SDRAM、DDR和DDR2、DDR3、DDR4的總線位寬均為64位 相當於路寬

可以通過命令行模式輸入『wmic memorychip』查看記憶體(RAM)的所有參數如上圖

ConfiguredClockSpeed DataWidth Voltage Speed TypeDetail
時鐘速度 位寬 電壓 工作頻率 記憶體容量

以DDR4-2400為例:

工作頻率:2400 MHz

位寬:64Bit=8Byte

 

例計算DDR4-2400記憶體(RAM)帶寬

2400MHz*64bit/8=19200 Mbyte/s=PC19200

例計算DDR400記憶體(RAM)帶寬

400MHz*64bit/8=3200Mbyte/s=PC3200

SolidWorks之更改語言

SolidWorks之更改語言

SolidWorks安裝後是默認是英文版,若想更改為正體字,但在Options卻沒有設定語言選項,因為SolidWorks是跟據Windows的地區格式(註冊表)而顯示語言

  1. x:\swwi\lang\chinese\setup.exe安裝中文語言包, x:為SolidWorks安裝光碟符號
  2. 檔案總管\控制台\地區\格式
  3. 格式選擇『中文(繁體,臺灣)』按『套用』
  4. 啟動SolidWorks即顯示正體字
  5. 若想顯示其它語言需在『x:\swwi\lang\』安裝語言包,然後更地區格式

若想更改為英文版則更簡單無需獨立安裝語言包

  1. 打開『功能表/系統選項/一般』
  2. 勾選『使用英文功能表』
  3. 啟動SolidWorks即顯示英文

3D打印-2.5寸轉3.5寸硬碟托架

3D打印-2.5寸轉3.5寸硬碟托架
3D打印-2.5寸轉3.5寸硬碟托架
3D打印-2.5寸轉3.5寸硬碟托架
3D打印-2.5寸轉3.5寸硬碟托架
3D打印-2.5寸轉3.5寸硬碟托架
3D打印-2.5寸轉3.5寸硬碟托架

SATA端口固態硬盤(Solid State Drives)大多為2.5寸.可直接在筆記本電腦上使用.但在臺式機使用3.5寸硬碟.有些廠家會附帶有2.5寸轉3.5寸硬碟托架,但有些廠家就無提供.我地可以通過3D打印機做出硬碟托架.另需要準備六粒3mm六角螺母.產品的效果比在網上買的金屬版還要好

  1. 運行SOLIDWORKS新建零件模型
  2. 選擇『前視基準面』作為草圖平面,繪畫厚2mm兩側高15mm的托架草圖 如上圖
  3. 使用『特徵/伸長填料』 方向選擇『兩則對稱』 深度填139mm生成托架本體
  4. 選擇托架本體一側繪畫兩個同心圓 直徑分別為12mm和4mm的『支柱草圖』
  5. 使用『特徵/伸長填料』 方向選擇『給定深度』深度填3mm生成『支柱本體』
  6. 選擇托架本體一側繪畫六邊形 內切圓直徑為8mm的『六角鑼母凹槽』草圖
  7. 使用『特徵/伸長除料』 方向選擇『給定深度』 深度填8mm生成『六角鑼母凹槽』本體
  8. 使用『特徵/參考幾何/基準軸』選擇『前視基準面』和『源點』生成『基準軸』
  9. 使用『特徵/直線複製排列』方向選擇『基準軸』副本數填2『特徵面』選擇『支柱』和『六角鑼母凹槽』生成兩個排列間距分別填41mm與101mm
  10. 使用『特徵/鏡射』鏡射面選『右視基準面』鏡射特徵選『支柱本體』和『六角鑼母凹槽』
  11. 選擇『上視基準面』作為草圖平面,繪畫3mm寬的槽口草圖 如上圖
  12. 使用『特徵/伸長填料』 方向選擇『給定深定』 深度填7mm生成槽口本體
  13. 選擇『上視基準面』作為草圖平面,繪畫距槽口邊距2mm方形草圖
  14. 使用『特徵/伸長除料』 方向選擇『至某面平移處』面選擇槽口頂部.偏移距離填2mm挖空『槽口』本體
  15. 使用『特徵/直線複製排列』方向選擇『基準軸』勾選間距和副本.間距填5mm副本數填2『特徵面』選擇『槽口』
  16. 使用『特徵/鏡射』鏡射面選『右視基準面』鏡射特徵選『槽口』本體
  17. 打印後把六粒鑼母鑲入凹槽

 

主板之微星(MSI)B350 GAMING PLUS安裝

主板之微星(MSI)B350 GAMING PLUS安裝
主板之微星(MSI)B350 GAMING PLUS安裝
主板之微星(MSI)B350 GAMING PLUS安裝
主板之微星(MSI)B350 GAMING PLUS安裝
主板之微星(MSI)B350 GAMING PLUS安裝
  1. 先安裝後置面板
  2. 確定你的主板鑼絲孔個數,ATX大板為9個.
  3. 在機箱安裝定位鑼絲,對齊主板鑼絲孔, 其它位置請勿安裝定位鑼絲,否則可能造成主板短路,無法開機.
  4. 如果機箱底板鑼絲孔反牙(滑牙),可反轉機箱底板使用小錘輕敲鑼絲孔圓邊,令鑼絲孔抓細
  5. 安裝主板前先通過接觸其它金屬物體釋放自身靜電.
  6. 拿起主板時手持主板邊緣,避面觸及主板的核心部件.
  7. 連接USB擴展面版,注意正反方向.
  8. 插STAT數據線時偏平介面端插在主板上
  9. SATA數據線時請勿對折成90度,否則傳送過程中可能會出現數據丟失.

安裝電源

  1. 安裝電源需要四粒鑼絲,電源線往內側的方向安裝
  2. 插ATX主板電源線(24線)
  3. 插CPU電源線12V (8線)

連接機箱前置面板插頭

  1. 主板JFP1連接機箱的開關和LED燈,早期 Power LED(電源燈)三插中間空,需要將正極(紅色)拔出插在中間.
  2. 主板JFP2連接機箱蜂鳴器
JFP1針腳 簡介 JFP1針腳 簡介
1 HDD LED+硬碟燈正極(紅色) 2 Power LED+電源燈正極(紅色)
3 HDD LED-硬碟燈負極 4 Power LED-電源燈負極
5 Reset Switch

重置開關

6 Power Switch

電源開關

7 8
9 Reserved(保留腳) 10 No Pin(無針腳)

 

JFP2針腳 簡介 JFP2針腳 簡介
1 Speaker-負極 2 Buzzer-負極
3 Buzzer-負極 4 Speaker+正極(紅色)

設定BIOS

  1. 按Delete進入主板BIOS
  2. Settings\Boot\Boot Option#1設定為你的啟動硬碟
  3. LAN Option ROM 設定為ON以啟動網卡
  4. HD Audio Controller設定為ON以啟動聲卡
  5. 按F9保存更改並重新啟
  6. 開機POST畫面時按F11進入啟動菜單
  7. 從菜單中選則你的Windows10安裝光盤或U盤

主板之微星(MSI)B350 GAMING PLUS

主板之微星(MSI)B350 GAMING PLUS
主板之微星(MSI)B350 GAMING PLUS

本想購買華碩(Asus)PRIME B350-PLUS但細梯之下此主板尺寸是30.5CM23.7CM(6個鑼絲固定孔)非標準ATX大板,而華碩稍貴點的主板尺寸都是30.4CM24.3CM(9個鑼絲固定孔)標準ATX大板,光從這點就可梯出華碩小氣.有朋友總是迷信華碩認為它的質量就是最好.但多年經驗告訴我並非這樣.

之後注意到微星(MSI)B350 GAMING PLUS這塊標準的ATX大板.整塊主版以紅黑色設計給人感觀非常好.最重要介面齊全,連舊式的串口和並口都支援(需外接埠).小小失望的是缺小IDE介面,幸好有PCI介面可插IDE擴展卡.但我又怕拖慢開機速度.

介面 簡介
CPU 支持AM4封裝AMD RYZEN

我不太注重CPU速度.買左盒裝銳龍1500X/3.5GHz/4核.

晶片組 AMD B350晶片組
內存 4條DDR4內存插槽雙通道內存構架.

安裝四條單條16GB剛好64GB內存

擴展插槽 一條PCIe3.0x16插槽(需要安裝RYZEN(銳龍)CPU)

一條PCIe2.0x16插槽

兩條PCIe2.0x1插槽

兩條PCI插槽.是我買它最重要原因,可以安裝我的PCI創新聲卡

USB後置面板

 

兩個USB2.0

四個USB3.1

一個USB3.1 TYPE-C

加上內置的USB插口,就無需再使用USB分線器.因為它經常接觸不良

交叉火力 支援安裝兩個相同的AMD顯卡

買左迪蘭恒進(ATALAND)RX550酷能4G

存儲 四個SATA 6Gb/s埠,安裝兩個硬盤一個DVD光驅剛剛夠用.

一個M.2介面

 

CPU之AMD RYZEN安裝

CPU之AMD RYZEN安裝
CPU之AMD RYZEN安裝
CPU之AMD RYZEN安裝

現在的CPU尺寸小而且針腳多.SOCKET AM4就有1331腳.若裝反會損毀CPU.是吾是想起SOCKET-1和SOCKET-A的年代呢.

安裝SOCKET AM4步驟

  1. 關閉電源並移除電源線.
  2. 輕撥並抬起AM插座杆至90度(垂直)
  3. AM4的CPU的表面有黃色三角標識.代表PIN1
  4. SOCKET AM4插槽的也有三角標識
  5. 將兩個三角形對齊把CPU平放插入插槽
  6. 把插槽杆拔回原位鎖定CPU
  7. 在CPU表面塗抹散熱矽膠,增加CPU與散熱器接觸面.
  8. 拆除用於安裝散熱器扣勾架(固定模塊)的四粒鑼絲(逆時針轉),露出用於鎖定散熱器的底板
  9. 把原裝幽靈風扇的鑼絲對散熱器底板鑼絲孔.
  10. 使用十字鑼絲批,四粒鑼絲要分開逐次拎,鑼絲不要一次拎緊. (順時針轉)
  11. 把四針風扇插頭插入主板的CPU_FAN1插座

CPU之AMD RYZEN5銳龍1500X

CPU之AMD RYZEN5銳龍1500X
CPU之AMD RYZEN5銳龍1500X
CPU之AMD RYZEN5銳龍1500X

以前好似無買過盒裝的CPU.都是買散裝CPU外加個散熱器.因為現在網購方便乾脆買個盒裝CPU.本想買個Intel八代酷睿I5但需要300系列主機板.CPU同樣是1151腳.但卻要新的晶片組支援.Intel這種作為實在吾好.

繼而把目光轉向AMD RYZEN(銳龍)5-1500X.擁有4個核芯.基頻3.5GHz而且不鎖頻.就這點就比Intel有誠意.

有很吾識多任務操作系統原理的人認為CPU速度比核芯個數重要.其實並非這樣.每個進程(Process)都有一個主線程(thread).瀏覽器+播放機+圖形介面+後臺任務.分分幾十個進程(Process)等代CPU時間片運行.如果你有多CPU核芯操作系統就會均勻的給CPU核芯分配時片.如果遊戲或程式創建多個線程(thread).更能充分的發繪多核CPU性能.最明顯的是兩核芯CPU一出現就令Windows假死現象消失,因為在單CPU年代如果某個進程嚴重佔用CPU資源,Windows圖形介面就變得很慢很慢.

所以在未有多核CPU出現前.解決辦法是購買雙CPU的主版加兩個CPU.但多核芯系統依然比不上多核芯多CPU系統,因為單個CPU的主版的多個核芯同時間只有單個可以訪問內存(RAM).而多CPU的主版則可以同時訪問內存(RAM).但多核的CPU核芯同時間依然只有單核個可以訪問內存(RAM).但我之前幾塊雙CPU的主版都無法啟動!_!

性能 產品規格
CPU AM4介面1331針

AMD RYZEN銳龍1500X不集成顯卡

核芯 4芯核8線程
頻率 基頻3.5GHz最高3.7GHz
緩存 L2=2MB

L3=16MB

風扇 原裝幽靈風扇
電壓 1.264V
基頻(CPU Base Clock) 100MHZ(基頻只有100超133有D希望)

 

記憶體之DDR4安裝

記憶體之DDR4安裝

以前主版的記憶體(RAM)插槽是隨便插的.但DDR4主機板會有記憶體(RAM)安裝建議.如下:

數量 插槽
一條 DIMMA2
兩條(雙通道) DIMMA2與DIMMB2
四條(雙通道) DIMMA1與DIMMB1

DIMMA2與DIMMB2

  1. 先通過接觸其它金屬物體釋放自身靜電,已免靜電損壞記憶體(RAM)
  2. 先拔開記憶體(RAM)插槽的扣勾
  3. 插的時候要注意記憶體(RAM)的缺口位.
  4. 將記憶體(RAM) 對準插槽用力按下,直到記憶體(RAM)完全到位.
  5. 如果記憶體(RAM)的金手指氧化接觸不良,可使用膠擦擦.

 

記憶體(RAM)之DDR4-64GB

記憶體(RAM)之DDR4-64GB
記憶體(RAM)之DDR4-64GB BIOS

在市面上無論原裝機、相容機還是平板電腦.最高我只見過是16GB的記憶體(RAM).用戶採用最強勁CPU最大硬盤.而往往忽略記憶體(RAM)容量嚴重不足的重要性.

在現代操作系統把記憶體(RAM)空間劃分成一頁(PAGE)一頁(PAGE)使用,如果沒有足夠記憶體(RAM)空間,操作系統會把以載入數據的記憶體(RAM)分頁(PAGE)寫入磁盤(DISK),以騰出足夠記憶體(RAM)空間.以免造成記憶體(RAM)溢出.但問題是磁盤(DISK)讀寫比記憶體(RAM)慢內太多.在多個程式(APP)切換時記憶體分頁(RAM PAGE)要在記憶體(RAM)和磁盤(DISK)之間不斷傳送.在瀏覽較大的PDF文檔時記憶體(RAM)不斷分配(malloc)和釋放(free)也會造成很大的延時.現代的網絡瀏覽器耗記憶體(RAM)更為利害,網絡影片再打開若干個網站.而後在各瀏覽頁面切換造成很大的延時. CPU再快都幫唔到你. 所以記憶體(RAM) 係多多益善.

VASEKY雖然是雜牌但勝在價格低廉,而且還裝有散熱器.但記憶體(RAM)發熱量不大對於超頻意義不大.只用作美觀和保護晶片.但比起其它大廠有誠意得多.安裝四條16GB共64GB是我這塊B350主版的極限.

參數 簡介
DDR4 2400MHZ(PC19200)
電壓 1.2V
容量 單條16GB

 

 

 

顯卡之迪蘭恒進(ATALAND)RX550酷能4G

顯卡之迪蘭恒進(ATALAND)RX550酷能4G
顯卡之迪蘭恒進(ATALAND)RX550酷能4G

本人對顯卡並無太多要求.能運行SolidWorks與Maya即可以.本想購買的XFX訊景R5-240無貨.而且又擔心4K影片支持.現在顯卡大多都被買去挖礦造成顯卡缺貨.幸好迪蘭恒進(ATALAND)RX550酷能4GB剛剛到貨馬上落單.

迪蘭恒進(ATALAND)RX550酷能4G 簡介
晶片組 RX550
內存 128BIT/DDR5/4GB
輸出 DVI-D/HDMI/DP

現在的顯卡以4GB顯存起步,回想起我第一塊顯卡只有1MB的顯存.更加認證左.硬體只是過眼雲煙.演算法才能久流傳.

3DMARK11 Entry(E) 1024×600 Performance(P)1280×720 Extrema(x)1920X1080
總分 E9283 P6332 X1398
圖形分數 9527 5929 1241
物理分數 8958 8922 8960
結合分數 8390 6844 1688
GT1 38.29幀 23.66幀 7.16幀
GT2 45.03幀 26.75幀 6.94幀
GT3 63.62幀 39.09幀 6.44幀
GT4 30.75幀 20.04幀 3.31幀
PT 28.44幀 28.32幀 28.45幀
CT 39.03幀 31.83幀 7.85幀

大量的光照對於GPU要求還是有點高,Extrema測試基本吾上10幀.

OpenGL之載入地形文檔

OpenGL之載入地形文檔

地形文檔就是256色位圖文檔,因為位圖即點陣圖.點的數值越大地形越高,數值越低形成低窪地帶.最終生成高山、湖水.

地形演示程式:下載

  1. 按+/-鍵移動煙霧距離
  2. 按{}鍵升高或降低湖水高度
  3. OPEN/FILE載入地形文檔,支持拖放.
  4. 只支持RAW格式
  5. 按ESC鍵重置聚地形文檔
  6. 壓縮包內的terrain目錄附有三個地形文檔

繪畫地形思路如下:

  1. 設地形的最大高度為10
  2. 湖水平面設為1
  3. 因為像素8Bit最大256色, 所以縮放因子等於256除以地形的最大高度scale=256/10
  4. 地形由三角形所組成, 遍曆所有像素生成三角形.
  5. 地形的顏色由綠色分量組成,Y座標越高顏色越明亮.
  6. 通過像素的索引生成三角形XZ座標
  7. 通過像素的顏色值生成三角形Y座標,Y=像素顏色/縮放因子
  8. 繪畫藍色湖水平面覆蓋低窪地帶

成生地形RAW文檔

  1. 打開Photoshop並載入高空拍攝圖
  2. 大小轉換為64*64像素
  3. 圖像/模式/灰度
  4. 圖像/模式/8位通道
  5. 儲存為.RAW文檔

繪畫地形的函式示例

void Draw_Terrain (PBYTE data,int height,int width)

{

for(int z=0;z < height-1; ++z)

{

glBegin(GL_TRIANGLE_STRIP);// 繪畫三角形

for(int x=0;x < width; ++x)

{

float scaled_height1 = data[ z   * width + x] / (256.0f / 10.0f);

float scaled_height2 = data[(z+1)* width + x] / (256.0f / 10.0f);

glColor3f(0.1f, 0.5f + 0.5f * scaled_height1 / 10, 0.1f);// 山地的顏色,地勢越高綠色分量越大

glVertex3f((x – width/2.0f), scaled_height1,(z – height/2.0f));

glColor3f(0.1f, 0.5f + 0.5f * scaled_height2 / 10, 0.1f);// 山地的顏色,地勢越高綠色分量越大

glVertex3f((x – width/2.0f), scaled_height2, ((z+1) – height/2.0f));

}

glEnd();

}

// 繪畫湖面

glColor3f(0.0, 0.0, 0.8f);// 藍色湖水

glBegin(GL_QUADS);

glVertex3f(-width/2.1f, 1,  height/2.1f);

glVertex3f( width/2.1f, 1,  height/2.1f);

glVertex3f( width/2.1f, 1, -height/2.1f);

glVertex3f(-width/2.1f, 1, -height/2.1f);

glEnd();

}

Windows資源文檔的編譯與讀取

Windows資源文檔的編譯與讀取

Windows程式就是單獨的.exe執行文件.但若程式需要讀取文檔才能運行.可以將其與.exe文件一起放置,但這樣就失去保密性.更好處理方法是將文檔編譯進.exe執行文件.這樣執行程式就無需附帶其它文檔.以VC為例:

把資源文檔編譯進.exe執行文件

  1. 在VC工程目錄創建名為”res”的目錄(其它名都可以)
  2. 把資源文檔當拷貝進”res”的目錄
  3. 以文本方式編輯rc文檔,寫入資源文檔的路徑
  4. name/ID flag   path
  5. 編譯器把所以資源文檔編譯成.RES文檔,最後與其它.obj文檔連接並生.exe執行文件
定義資源文檔 簡介
resources.rc

Heightmap  RAW  “res\\heightmap.raw”

通過字符串名定義

RAW為類型名

Heightmap為資源名

resource.h

#define  ID_MAP   1500

resources.rc

ID_MAP  RAW  “res\\heightmap.raw”

通過整數標識符定義

ID_MAP為資源ID

也可直接使用數字

讀取資源文檔示例

  1. 查找資源FindResource()
  2. 加載資源LoadResource()
  3. 獲取文檔的長度SizeofResource()
  4. 鎖定資源並獲取指針LockResource()

C代碼版本

hInstance:程式的實例句柄

filename:資源文檔名

type:類型名

PBYTE Read_RES(HINSTANCE hInstance,char *filename,char * type)

{//  查找資源

HRSRC hRsrc =::FindResource((HMODULE)hInstance,filename,type);

if(hRsrc == NULL)

return false;

//加載資源

HMODULE hGlobal = (HMODULE)::LoadResource((HMODULE)hInstance,hRsrc);

// 獲取文檔的字節長度

int size =::SizeofResource((HMODULE)hInstance,hRsrc);

// 鎖定資源並獲取指針

PBYTE res = (PBYTE) ::LockResource(hGlobal);

// 分配內存空間

PBYTE data = (PBYTE)malloc(size);

// 拷貝數據

memcpy(data,res,size);

if(hGlobal)

FreeResource(hGlobal); // 釋放資源句柄

return data;

}

OpenGL之煙霧

OpenGL之煙霧

煙霧(Fog)使遠距離的物體變暗,近距離的物體變得清晰.是遊戲中常用特效.OpenGL煙霧將每個像素煙霧色進行混合處理.

煙霧演示程式:下載

  1. 按+/-鍵移動煙霧距離
  2. 按ESC鍵重置聚煙霧

煙霧函式演示:

  1. glEnable(GL_FOG);
  2. GLfloat fogColor[] = { 0f, 0.0f, 0.0f };
  3. glFogfv(GL_FOG_COLOR, fogColor);
  4. glFogi(GL_FOG_MODE, GL_LINEAR);
  5. glFogi(GL_FOG_COORD_SRC,GL_FRAGMENT_DEPTH);
  6. glFogf(GL_FOG_START, start);
  7. glFogf(GL_FOG_END, end);
  8. glFogf(GL_FOG_DENSITY, 2f);
  9. Draw_Terrain();
  10. glDisable(GL_FOG);

OpenGL通過glFog()函式設定的距離、顏色、密度生成煙霧

參數 簡介
glFogi(GL_FOG_MODE, GL_LINEAR); 設定混合方程式

GL_LINEAR:線性混合

GL_EXP:指數混合(默認值)

GL_EXP2:二次指數指數混合

glFogf(GL_FOG_DENSITY, 1.2f); 煙霧的單位密度,數值需為正,默認值為1.0
glFogf(GL_FOG_START, start); 煙霧距離視口的近端距離
glFogf(GL_FOG_END, end); 煙霧距離視口的遠端距離
glFogi(GL_FOG_INDEX, 0); 設定煙霧顏色8位調色版索引
GLfloat fogColor[] = { 0.5f, 0.5f, 0.5f };

glFogfv(GL_FOG_COLOR, fogColor);

設定煙霧顏色(RGB),默認為黑色.
glFogi(GL_FOG_COORD_SRC,

GL_FRAGMENT_DEPTH);

深度值

GL_FRAGMENT_DEPTH:視口與煙霧的距離(默認值)

GL_FOG_COORD:使用glFogCoordf();設定煙霧坐標

 

混合方程式 簡介
Color=blendFactor*in + (1-blendFactor)*fog 混合方程式
blendFactor 混合因子
in 輸入顏色
fog 煙霧顏色
Color 輸出顏色

 

混合因子方程式 簡介
GL_LINEAR 線性混合

blendFactor=(end-depth)/(end-start)

GL_EXP 指數混合(默認值)

blendFactor= EXP (e, -density*depth)

GL_EXP2 二次指數指數混合

blendFactor= EXP(EXP (e, -density*depth),2)

 

Windows菜單之多選與單選

Windows菜單之多選與單選

Windows菜單可以通過實現單選(點選)與多選(勾選)展現當前狀態.你無需更改MENU結構,只需運行時更改菜單項MENUITEM的標記.

菜單多選與單選(函式示例) 簡介
HMENU menu = GetSubMenu(main_menu,1); 獲取子菜單句柄
CheckMenuRadioItem(

menu,

ID_FIRST,

ID_LAST,

ID_CHECK,

MF_BYCOMMAND);

單項選擇

ID_FIRST第一個菜單

ID_LAST最後一個菜單ID

ID_CHECK單選(點選)菜單ID

 

CheckMenuItem(menu,

ID_CHECK,

MF_BYCOMMAND|MF_CHECKED);

選擇多個菜單項(多項選擇)
CheckMenuItem(menu,

ID_CHECK,

MF_BYCOMMAND|MF_UNCHECKED);

取消選擇菜單項(多項選擇)

 

 

 

 

 

 

 

OpenGL之顏色混合

OpenGL之顏色混合

OpenGL之顏色混合alpha通過glBlendFunc()設定的混合因子生成透明效果,但通過其它的混合因子可產生更多不同的混合效果.令外OpenGL的顏色混合是無需啟用光照的glEnable(GL_LIGHTING); 但需要啟動多邊形隱面裁剪::glEnable(GL_CULL_FACE);否則會有一面會繪畫錯誤.

混合因子演示程式.下載

  1. 設定Sour Factor選擇”來源混合因子”
  2. 設定Dest Factor選擇”目標混合因子”
  3. 設定Blend Equation選擇”混合公式”
glBlendFunc()的混合公式 簡介
GL_FUNC_ADD C =(Cs*S)+(Cd*D) 默認值
GL_MIN C =MIN(Cs,Cd)
GL_MAX C =MAX(Cs,Cd)
GL_FUNC_SUBTRACT C =(Cs*S)-(Cd*D)
GL_FUNC_REVERSE_SUBTRACT C =(Cd*S)-(Cs*D)

 

公式因子 簡介:混合因子的簡介可通過最下表查閱
Cs: 來源顏色
S: 來源混合因子
Cd: 目標顏色
D: 目標混合因子

 

S來源混合因子 簡介
GL_ZERO sour (r,g,b,a) *{0,0,0,0}
GL_ONE sour (r,g,b,a) * (1,1,1,1)
GL_DST_COLOR sour (r,g,b,a) * dest (r,g,b,a)
GL_ONE_MINUS_DST_COLOR sour (r,g,b,a) * ((1,1,1,1)- dest(r,g,b,a))
GL_SRC_ALPHA sour (r,g,b,a) * sour(alpha)
GL_ONE_MINUS_SRC_ALPHA sour (r,g,b,a) * (1- sour(alpha))
GL_DST_ALPHA sour (r,g,b,a) * dest(alpha)
GL_ONE_MINUS_DST_ALPHA sour (r,g,b,a) * (1- dest(alpha))
GL_SRC_ALPHA_SATURATE sour (r,g,b,a) * MIN(sour(alpha),1-dest(alpha))
GL_CONSTANT_COLOR sour (r,g,b,a)* Color(r,g,b,a)
GL_ONE_MINUS_CONSTANT_COLOR sour (r,g,b,a)*( (1,1,1,1)- Color(r,g,b,a))
GL_CONSTANT_ALPHA sour (r,g,b,a)* Color(alpha)
GL_ONE_MINUS_CONSTANT_ALPHA sour (r,g,b,a)*(1-Color(alpha))

 

D目標混合因子 簡介
GL_ZERO dest (r,g,b,a) *{0,0,0,0}
GL_ONE dest (r,g,b,a) * (1,1,1,1)
GL_SRC_COLOR dest (r,g,b,a) * sour (r,g,b,a)
GL_ONE_MINUS_SRC_COLOR dest (r,g,b,a) * ((1,1,1,1)- sour (r,g,b,a))
GL_SRC_ALPHA dest (r,g,b,a) * sour (alpha)
GL_ONE_MINUS_SRC_ALPHA dest (r,g,b,a) * (1- sour (alpha))
GL_DST_ALPHA dest (r,g,b,a) * dest (alpha)
GL_ONE_MINUS_DST_ALPHA dest (r,g,b,a) * (1- dest (alpha))
GL_SRC_ALPHA_SATURATE dest (r,g,b,a) * MIN(sour(alpha),1-dest(alpha))
GL_CONSTANT_COLOR dest (r,g,b,a)* Color(r,g,b,a)
GL_ONE_MINUS_CONSTANT_COLOR dest (r,g,b,a)*( (1,1,1,1)- Color(r,g,b,a))
GL_CONSTANT_ALPHA dest (r,g,b,a)* Color(alpha)
GL_ONE_MINUS_CONSTANT_ALPHA dest (r,g,b,a)*(1-Color(alpha))

上表的Color混合常量通過glBlendColor()設定

設定混合常量 簡介
Void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha; 混合常量默認為(0,0,0,0)作為混合權重係數

 

OpenGL之顏色混合alpha

OpenGL之顏色混合alpha

顏色混合(alpha)可實現透明的視角效果,可以模擬液體、玻璃等.當你啟動混合OpenGL將輸入源的顏色與和在幀緩存裏的顏色混合

函式 簡介
glEnable(GL_BLEND); 啟用混合
glDisable(GL_BLEND); 禁用混合
函式 簡介
Void glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); 設定顏色和透明度
red, green, blue 顏色
alpha 透明度數值範圍:0.0f-1.0f

0:全透明

1:完全不透明

函式示例

  1. glEnable(GL_BLEND);// 啟用混合
  2. glDepthMask(GL_FALSE);// 將深度環存設置為只讀
  3. glBlendFunc(GL_SRC_ALPHA,GL_ONE); // 透明效果
  4. glColor4f(1.0f, 1.0f, 1.0f,alpha);//月球模型顏色
  5. auxSolidSphere(1.0f);// 繪畫
  6. glDepthMask(GL_TRUE);// 將深度環存設置為可讀可寫
  7. glDisable(GL_BLEND);// 禁用混合
混合函式 簡介
void glBlendFunc (GLenum sfactor, GLenum dfactor); 設定來源和目標混合係數
sfactor 輸入源數據的混合係數
dfactor 當前幀緩存的混合係數

 

混合係數 簡介
GL_ZERO 將顏色設為{0,0,0,0}
GL_ONE 不改變當前顏色(r,g,b,a)*(1,1,1,1)
GL_SRC_COLOR 目標與來源相乘dest (r,g,b,a)* sour (r,g,b,a)
GL_DST_COLOR 來源與目標相乘sour (r,g,b,a)* dest (r,g,b,a)
GL_ONE_MINUS_SRC_COLOR (r,g,b,a)*((1,1,1,1)- sour(r,g,b,a))
GL_ONE_MINUS_DST_COLOR (r,g,b,a)*((1,1,1,1)- dest(r,g,b,a))
GL_SRC_ALPHA (r,g,b,a) * sour(alpha)
GL_DST_ALPHA (r,g,b,a) * dest(alpha)
GL_ONE_MINUS_SRC_ALPHA (r,g,b,a) * (1- sour(alpha))
GL_ONE_MINUS_DST_ALPHA (r,g,b,a) * (1- dest(alpha))
GL_SRC_ALPHA_SATURATE (r,g,b,a) *MIN (sour(alpha),1-dest(alpha))

 

函式 簡介
glEnable(GL_DEPTH_TEST); 打開深度檢測(Z軸緩存), 一定要調用.保證光照正確繪製和模形前後正確繪製

Alpha演示程式示例,分別有太陽,地球和月球.下載程式

  1. 按+/-鍵增加或減小月球透明度
  2. 按SPACE(空格)鍵啟用或禁用聚光燈
  3. 按UP/DOWN鍵相機前後移動
  4. 按LEFT/RIGHT鍵相機左右旋轉
  5. 按F1鍵打開幫助
  6. 按ESC鍵重置聚光燈參數

OpenGL之鏡面反射光

OpenGL之鏡面反射光

鏡面反射產生閃耀的光輝,此光照效果很有趣,需要分別設置光源材質.

光源和材質 簡介
Light_Specular[] = {1.0f,1.0f,1.0f,1.0f};

glLightfv(light,GL_SPECULAR, Light_Specular);

鏡面反射光顏色{r,g,b,a}分量
Material_Specular[] = {1.0f,1.0f,1.0f,1.0f};

glMaterialfv(GL_FRONT,GL_SPECULAR, Material_Specular);

材質的鏡面反射光顏色,反射出去的顏色不大於材質顏色

{1.0f,1.0f,1.0f,1.0f}:光照完全反射出去,

glMaterialf (GL_FRONT,GL_SHININESS,10); 鏡面反射光聚焦度

0:不聚焦

128:高度聚焦

函式示例

  1. float Light_Specular[] = {0f,1.0f,1.0f,1.0f};// 鏡面反射光分量
  2. float Light_Position[] = {0f,0.0f,1.0f,1.0f};// 燈光位置
  3. glLightfv(light,GL_SPECULAR, Light_Specular);// 鏡面反射光分量
  4. glLightfv(light,GL_POSITION, Light_Position);// 光源位置
  5. Material_Specular[] = {0f,1.0f,1.0f,1.0f};// 鏡面反射光材質
  6. glMaterialfv(GL_FRONT,GL_SPECULAR, Material_Specular);// 鏡面反射光材質
  7. glMaterialf (GL_FRONT,GL_SHININESS,10);// 鏡面反射光聚焦度

鏡面反射光程式示例,行星發出閃耀的光輝,而衛星繞行星旋轉並且發光,分別使用聚光燈和定點光.但無使用環境光.下載程式

  1. 按(/)鍵增加或減小聚光燈焦點指數
  2. 按</>鍵增加或減小聚光燈張角
  3. 按+/-鍵增加或減小多邊形表面的鏡面反射光聚焦度
  4. 按123鍵切換衛星的顏色與光線(紅綠藍)
  5. 按SPACE(空格)鍵啟用或禁用聚光燈
  6. 按UP/DOWN鍵衛星上下移動
  7. 按LEFT/RIGHT鍵衛星左右移動
  8. 按F1鍵打開幫助
  9. 按ESC鍵重置聚光燈參數

 

OpenGL之材質

OpenGL之材質

OpengGL為多邊形設置材質屬性,根據紅綠藍RGB的分量而確定反射光顏色:如下表:

材質 光源的光顏 反射光顏色, 簡介
綠色(0,1,0) 白色(1,1,1) 綠色(0,1,0) 只反射綠光
綠色(0,1,0) 紅色(1,0,0) 黑色(0,0,0) 只反射黑光

 

材質 簡介
void glMaterialf(GLenum face, GLenum pname, GLfloat param); 為多邊形設置材質屬性用於光照計算,它是全局性的, 影響所有繪製的多邊形,直到在次調用
void glMaterialfv(GLenum face, GLenum pname, const GLfloat *params); glMaterialf()數組版本

 

face 簡介
GL_FRONT 材質僅應用於多邊形正面
GL_BACK 多邊形反面
GL_FRONT_AND_BACK 多邊形的正反面

 

pname 數值 簡介
GL_AMBIENT {r,g,b,a} 材質的環境光顏色
GL_DIFFUSE {r,g,b,a} 材質的散射光顏色
GL_AMBIENT_AND_DIFFUSE {r,g,b,a} 同時設置材質的環境光和散射光顏色
GL_SPECULAR {r,g,b,a} 材質的鏡面反射光顏色,反射出去的顏色不大於材質顏色

{1.0f,1.0f,1.0f,1.0f}:光會完全反射出去

GL_SHININESS 0-128 鏡面反射光指數

0:不聚焦

128:高度聚焦

GL_EMISSION {r,g,b,a} 材質的反射光顏色

設置多邊形材質的環境光和散射光,函式示例:

  1. glEnable(GL_LIGHTING); // 啟用光照
  2. float white[] = {0f,1.0f,1.0f,1.0f};// 白色
  3. glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white);// 設置材質

OpenGL之聚光燈

OpenGL之聚光燈

聚光燈:在定點光源的基礎加上光線輻射方向,因此光線呈圓錐.

聚光燈參數 範圍 簡介
GL_SPOT_DIRECTION (x,y,z) 聚光燈指向/方向3D矢量

默認值:(0,0,-1)

GL_SPOT_EXPONENT 0-128 焦點/指數:光線從焦點到圓錐的邊界,光的強度不斷衰減,直到邊界消失.

指數越大焦點越小

指數越小焦點越大

GL_SPOT_CUTOFF 0.1-90 圓錐面與指向軸的角度(圓錐角),所以聚光燈的張角為圓錐角的2倍.

張角=圓錐角*2

聚光燈函式使用示例

  1. float Spot_Direction[] = {0f,0.0f,-1,0.0f}; // 聚光燈的指向
  2. float Light_Ambient[] = {0f,1.0f,1.0f,1.0f};// 環境光
  3. float Light_Diffuse[] = {0f,1.0f,1.0f,1.0f};// 散射光
  4. float Light_Position[] = {0f,0.0f,1.0f,1.0f};// 光源位置
  5. glEnable(GL_LIGHTING); // 啟用光照
  6. glLightfv(light,GL_AMBIENT, Light_Ambient);// 環境光分量
  7. glLightfv(light,GL_DIFFUSE, Light_Diffuse);// 散射光分量
  8. glLightfv(light,GL_POSITION,Light_Position);// 光源位置
  9. glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 0f); // 設置聚光燈的角度
  10. glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION, Spot_Direction); // 設置聚光燈的
  11. glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 0f); // 設置聚光燈的指數
  12. glEnable(GL_LIGHT0); // 啟用燈光

聚光燈程式示例,可分別設定張角與焦點.下載

  1. 按(/)鍵增加或減小聚光燈焦點指數
  2. 按[/]鍵增加或減小聚光燈張角
  3. 按+/-鍵增加或減小聚光燈亮度
  4. 按SPACE(空格)鍵啟用或禁用聚光燈
  5. 按UP/DOWN鍵正方體繞X軸旋轉
  6. 按LEFT/RIGHT鍵正方體繞Y軸旋轉
  7. 按F1鍵打開幫助
  8. 按ESC鍵重置聚光燈參數

 

OpenGL之法線

OpenGL之法線

法線:即垂直於其表面的單位矢量

OpenGL在進行光照運算前需先計算法線,光與表面相交的角度利用法先計算出反射角度,結合光照與材質計算表面的顏色

法線函式 簡介
void glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz); 設置法線

(nx,ny,nz):法線坐標分量

法線函式示例

glBegin(GL_POLYGON);

glNormal3f(0.0f,1.0f,0.0f);// 法線

glVertex3f( 0.5f, 0.5f, 0.5f);

glVertex3f( 0.5f, 0.5f,-0.5f);

glVertex3f(-0.5f, 0.5f,-0.5f);

glVertex3f(-0.5f, 0.5f, 0.5f);

glEnd();

法線的計算 簡介
A*B=(Ax*Bz-Az*By, Az*Bx-Ax*Bz, Ax*By-Ay*Bx) 矢量A和B叉積方程

計算兩個3D向量的法線(叉積)

void Cross(float pa[3], float pb[3], float pc[3],float normal[3])

{

float va[3],vb[3];//矢量1,矢量2

float length;//矢量長度

// 計算矢量1

va[0] = pa[0] – pb[0];

va[1] = pa[1] – pb[1];

va[2] = pa[2] – pb[2];

// 計算矢量2

vb[0] = pb[0] – pc[0];

vb[1] = pb[1] – pc[1];

vb[2] = pb[2] – pc[2];

// 計算叉積

normal[0] = va[1]vb[2] – va[2]vb[1];

normal[1] = va[2]vb[0] – va[0]vb[2];

normal[2] = va[0]vb[1] – va[1]vb[0];

// 計算長度

length = sqrt(normal[0]normal[0] + normal[1]normal[1] + normal[2]*normal[2]);

// 計算單位矢量

normal[0] = normal[0] / length;

normal[1] = normal[1] / length;

normal[2] = normal[2] / length;

}

法線演示程式,旋轉正方體觀看光照的變化如上圖:下載

  1. 按+/-鍵增加或減小光照亮度
  2. 按SPACE(空格)鍵啟用或禁用光照
  3. 按UP/DOWN鍵正方體繞X軸旋轉
  4. 按LEFT/RIGHT鍵正方體繞Y軸旋轉
  5. 按Z+LEFT/Z+RIGHT鍵正方體繞Z軸旋轉
  6. 按F1鍵打開幫助
  7. 按ESC鍵重置模型旋轉角度

 

OpenGL之光照

OpenGL之光照

OpenGL光的顏色由紅綠藍(RGB)的分量確定,當光照到表面時,由表面的材質的確定反射的光的顏色(RGB).

OpenGL光有四類 簡介
環境光 無特定照射方向,太陽光
漫射光 有照射方向的光,遇表面光將朝反方向照射, 如燈光不受相機位置影響.
反射光 有照射方向,遇表面光將朝反方向照射.如亮光但受相機位置影響.
放射光 只增加物體的亮度

 

OpenGL光照影響因素 簡介
光源 環境光、漫射光、反射光、放射光
材質 確定反射光RGBA值
法線 由表面的頂點計算方向
相機位置 當光折射時, 相機位置影響反射光的計算

 

光的顏色、位置、方向的設定:
void glLightfv (GLenum light, GLenum pname, const GLfloat *params);

 

glLightfv()參數 簡介
light GL_LIGHT0~ GL_LIGHT7

OpenGL最多可以指定8個光源

pname 光源的參數名見下表
Params 光源的參數值

 

光源的參數名Pname 簡介
GL_AMBIENT 環境光向所有方向照射
GL_DIFFUSE 漫射光具有方向,碰撞到FACE會進行反射
GL_SPECULAR 鏡面反射光
GL_POSITION 光的位置
GL_SPOT_DIRECTION 聚光燈的矢量方向
GL_SPOT_EXPONENT 聚光燈的指數
GL_SPOT_CUTOFF 聚光燈的邊界
GL_CONSTANT_ATTENUATION 衰減值係數常量
GL_LINEAR_ATTENUATION 線性衰減值係數
GL_QUADRATIC_ATTENUATION 二次衰減值係數

 

環境光 簡介
Pname=GL_AMBIENT 環境光
Params=(x,y,z,w) 顏色分量
w=alpha w=0透明

w=1實體

float Light_Ambient[] = { 1.0f,1.0f,1.0f,1.0f};

glLightfv(GL_LIGHT0,GL_AMBIENT, Light_Ambient);

亮白的環境光示例

 

漫射光 簡介
GL_DIFFUSE 漫射光
Params=(x,y,z,w) 顏色分量
w=alpha w=0透明

w=1實體

float Light_Diffuse[] = { 1.0f,1.0f,1.0f,1.0f};

glLightfv(GL_LIGHT0,GL_DIFFUSE, Light_Diffuse);

亮白的漫射光示例

 

光源的位置 簡介
Pname= GL_POSITION 設定光源的位置
Params=(x,y,z,w) 向量或坐標
w=0 定向光源(x,y,z)為向量定義光的照射方向,如太陽.
W=1 定點光源(x,y,z)為坐標定義光源的位置,如燈泡.
float Light_Position[] = {0.0f,0.0f,0.0f,1.0f };

glLightfv(GL_LIGHT0,GL_POSITION,Light_Position);

光源的位置設在原點

 

光衰減(OpenGL支持三類光衰減) 默認值 簡介
ATTENUATION 光線隨著距離的增大其強度減小,但只適用於定點光源,但定向光源是無窮遠的設置衰減是無意義.

衰減因子*光強度 = 光衰減

GL_CONSTANT_ATTENUATION 1.0f 衰減值係數常量
GL_LINEAR_ATTENUATION 0.0f 線性衰減值係數
GL_QUADRATIC_ATTENUATION 0.0f 二次衰減值係數

光照亮度演示程式,定點光源並且全方位輻射.如上圖:下載

  1. 按+/-鍵增加或減小光照亮度
  2. 按SPACE(空格)鍵啟用或禁用光照
  3. 按UP/DOWN鍵正方形繞X軸旋轉
  4. 按LEFT/RIGHT鍵正方形繞Y軸旋轉
  5. 按Z+LEFT/Z+RIGHT鍵繞Z軸旋轉
  6. 按F1鍵打開幫助
  7. 按ESC鍵重置模型旋轉角度

 

OpenGL之漸變

OpenGL之漸變

OpenGL可對每個頂點設定不同的顏色,令模型產生漸變效果.

漸變函式示例:

  1. glShadeModel(GL_SMOOTH);啟用漸變
  2. glBegin(GL_QUADS);繪畫四邊形
  3. glColor3f(0f, 0.0f, 0.0f);glVertex3f(0.0f, 0.0f, 0.0f);黑色
  4. glColor3f(0f, 0.0f, 1.0f);glVertex3f(0.0f, 0.0f, 1.0f);藍色
  5. glColor3f(0f, 0.0f, 1.0f);glVertex3f(1.0f, 0.0f, 1.0f);紫紅色
  6. glColor3f(0f, 0.0f, 0.0f);glVertex3f(1.0f, 0.0f, 0.0f);紅色
  7. glEnd();
漸變 簡介
void glShadeModel (GLenum mode); 設定模型漸變模式(mode)

獲取當前使用的漸變模式

  1. GLenum mode;
  2. glGetIntegerv( GL_SHADE_MODEL,&mode);
漸變模式(mode) 簡介
GL_FLAT 單調,只應用單色
GL_SMOOTH 漸變(默認)

 

GL_FLAT單調顏色應用 簡介
GL_POINTS 應用最後一個頂點的顏色
GL_LINES
GL_TRIANGLES
GL_QUADS
GL_LINE_LOOP 應用分段的第二個頂點的顏色
GL_LINE_STRIP
GL_TRIANGLE_STRIP 應用最後一個頂點的顏色
GL_TRIANGLE_FAN
GL_ GL_QUAD_STRIP
GL_POLYGON 應用第一個頂點的顏色

漸變演示程式:下載

  1. 按UP/DOWN鍵繞X軸旋轉
  2. 按LEFT/RIGHT鍵繞Y軸旋轉
  3. 按Z+LEFT/Z+RIGHT鍵繞Z軸旋轉
  4. 按F1鍵打開幫助
  5. 按ESC鍵模型旋轉角度重置
  6. 按SPACE鍵切換漸變模式

 

OpenGL之屬性

OpenGL之屬性

OpenGL擁有幾百個狀態,通過屬性堆棧的壓棧和出棧,保存與恢復狀態變量.

函式 簡介
void glPushAttrib (GLbitfield mask); 把當前狀態壓入堆棧

Mask:掩碼,保存指定屬性分組

void glPopAttrib (void); 屬性堆棧出棧並恢復狀態

 

掩碼mask 屬性分組
GL_ALL_ATTRIB_BITS 所有屬性分組的OpenGL的狀態變量
GL_VIEWPORT_BIT 視口狀態變量
GL_ENABLE_BIT 以啟用的狀態變量
GL_FOG_BIT 煙霧狀態變量
GL_LIGHTING_BIT 燈光狀態變量
GL_LINE_BIT 直線狀態變量
GL_POINT_BIT 質點狀態變量
GL_POLYGON_BIT 多邊形狀態變量
GL_TEXTURE_BIT 紋理狀態變量

 

OpenGL之變換

OpenGL之變換

渲染3D場景時頂點在最終被渲染到屏幕上之前需經過四類變換

變換(TRANSFORMATION) 簡介
視圖變換(VIEW transformation) 設定攝影機CAMERA的位置
模型變換(MODEL transformation) 移動、旋轉、縮放多邊型模型,將模型局部坐標轉為世界坐標.
投影變換(PROJECTION transformation) 設定視口面積和裁剪平面,用於確定那些多邊型模型位於視口之內.
視口變換(Viewport transformation) 將剪切坐標影射到2D視口(屏幕)
模型視圖變換(modelview transformation) OpenGL將視圖變換與模型變換組合成單獨的模型視圖變換

視圖變換(VIEW transformation) 即攝影機的設定有三種放法,先將觀察矩陣載入單位矩陣glLoadIdentity();相機為於原點,朝向為負Z軸,上方向量為正Y軸.

視圖變換(VIEW transformation) 簡介
gluLookAt () 設定攝影機的位置和方向
glRotatef ()與glTranslatef() 攝影機CAMERA固定在原點,使用旋轉和平移在世界坐標中移動所有模型

模型變換(MODEL transformation)是指通過平移、縮放、旋轉將模型定位與定向

模型變換(MODEL transformation) 簡介
平移glTranslatef() 模型沿向量進行移動
旋轉glRotatef() 模型繞向量進行旋轉
縮放glScalef() 在XYZ三軸指定不同縮放係數放大或縮小模型

投影變換(PROJECTION transformation)是指設定視口面積和裁剪平面,它在模型變換與視圖變換之後執行,用於確定那些多邊型模型位於視口之內.在設定投影之前需要選擇投影矩陣堆棧glMatrixMode(GL_PROJECTION);和載入單位矩陣glLoadIdentity();OpenGL支持兩類投影

投影變換(PROJECTION transformation) 簡介
透視投影

glFrustum()

gluPerspective()

用於3D世界的顯示與真實世界一樣, 多邊型模型呈現近大遠小
正交投影

glOrtho()

gluOrtho2D()

不考濾與攝影機的距離,顯示多邊型模型真實的大小,常用於CAD軟件和2D遊戲

視口變換(Viewport transformation)發生在投影變換之後,視口是指渲染的2D窗口的大小和方向

視口變換(Viewport transformation) 簡介
glViewport() 每當窗口大小發生改變都要重設視口大小

矩陣堆棧

OpenGL的變換運算均對矩陣堆棧的棧頂進行操作.

OpenGL矩陣堆棧 簡介
Modelview Matrix Stack 模型視圖矩陣堆棧
Projection Matrix Stack 投影矩陣堆棧
TEXTURE Matrix Stack 紋理矩陣堆棧
ATTRIB Matrix Stack 屬性矩陣堆棧
CLIENT ATTRIB Matrix Stack 剪切屬性矩陣堆棧
NAME Matrix Stack

 

OpenGL之相機-旋轉和平移

OpenGL之相機-旋轉和平移

相機CAMERA固定在原點,通過旋轉和平移在世界坐標中移動所有模型

相機設定示例:

  1. glMatrixMode(GL_MODELVIEW);設定模型視圖矩陣
  2. glLoadIdentity()將觀察矩陣載入單位矩陣,相機位於原點(0,0,0), 朝向為負Z軸 (0,-90,0)
  3. glRotatef(AngleZ,0f,0.0f,1.0f); 橫搖/側滾角繞Z軸旋轉
  4. glRotatef(AngleY+90,0f,1.0f,0.0f); 偏航/航向角繞Y軸旋,補償90度
  5. glRotatef(AngleX,0f,0.0f,0.0f); 傾斜/俯仰角繞X軸旋轉
  6. glTranslatef(-posX,-posY,-posZ);移動模型坐標
視圖變換(VIEW transformation) 簡介
void glRotatef (

GLfloat angle,

GLfloat x, GLfloat y,GLfloat z);

旋轉

Angle:旋轉角度

x,y,z:軸向量

void glTranslatef (

GLfloat x, GLfloat y, GLfloat z);

平移

x,y,z:偏移向量

 

旋轉
glRotatef(AngleZ,0.0f,0.0f,1.0f); Z軸 橫搖/側滾
glRotatef(AngleY+90,0.0f,1.0f,0.0f); Y軸補償+90度 偏航/航向
glRotatef(AngleX,1.0f,0.0f,0.0f); X軸 傾斜/俯仰

 

平移 簡介
glTranslatef(-posX,-posY,-posZ); 反方向移動模型坐標

相機移動程式演示:下載

  1. 按UP/DOWN鍵前後移動
  2. 按LEFT/RIGHT鍵左右旋轉,繞Y軸旋轉
  3. 小鍵盤4/6繞Z軸旋轉
  4. 小鍵盤8/2繞X軸旋轉
  5. 按F1鍵打開幫助
  6. 按ESC鍵相機返回原點

OpenGL之相機 gluLookAt()

OpenGL之相機 gluLookAt()

函式gluLookAt()允許你設定相機的位置、方向、朝上向量

相機設定示例:

  1. glMatrixMode(GL_MODELVIEW);設定模型視圖矩陣
  2. glLoadIdentity()將觀察矩陣載入單位矩陣,相機為於原點,朝向為負Z軸,上方向量為正Y軸.
  3. gluLookAt() 相對于原點在移動相機
函式 數值 簡介
void gluLookAt (    
GLdouble eyex, 0.0f,0.0f,0.0f, 相機位置設為原點
GLdouble eyey,
GLdouble eyez,
GLdouble centerx, 0.0f,0.0f,-100.0f, 相機朝向負Z軸
GLdouble centery,
GLdouble centerz,
GLdouble upx, 0.0f,1.0f,0.0f 上方向量為正Y軸
GLdouble upy,
GLdouble upz);

 

位置和方向計算 簡介
radians = 3.141592654f * angleA / 180.0f; AngleA: Y軸角度

Radians: 弧度

pos=pos – (speed * cos(radians)); Pos:相機的位置

Speed:移動速度

target=pos+dist*cos(radians); Dist:視距

Target:相機的朝向

相機移動程式演示:下載

  1. 按UP/DOWN鍵前後移動
  2. 按LEFT/RIGHT鍵左右旋轉
  3. 按F1鍵打開幫助
  4. 按ESC鍵相機返回原點
  5. 按+鍵加大直線寬度
  6. 按-鍵減小直線寬度
  7. 按S鍵切換抗鋸齒功能
  8. 按.鍵切換四邊形點畫模式
  9. 按1鍵切換為黃色
  10. 按2鍵切換為綠色
  11. 按3鍵切換為紅色
  12. 按4鍵填充模式
  13. 按5鍵線框模式
  14. 按6鍵頂點模式

OpenGL之視口變換

OpenGL之視口變換

視口(Viewport)即渲染窗口大小,每當窗口大小發生改變都要使用glViewport()進行設定.視口變換在投影變換之後進行

視口設定 簡介
void glViewport(

GLint x, GLint y, 視口的左下角坐標

GLsizei width, 視口的寬度

GLsizei height); 視口的高度

視口的左下角坐標設為0,0

視口的寬高設為窗口大寬高

 

重設窗口大小,在WM_SIZE(窗口大小發生改變)消息下調用

  1. glViewport(0,0,width,height);將視口重置為新的尺寸
  2. glViewport(0,0,OpenGL_Width,OpenGL_Height);
  3. glMatrixMode(GL_PROJECTION); 設定投影矩陣
  4. glLoadIdentity();載入單位矩陣
  5. gluPerspective(0f, Width/Height,1.0f,1000.0f);
  6. glMatrixMode(GL_MODELVIEW);設定模型視圖矩陣
  7. glLoadIdentity();載入單位矩陣

 

OpenGL之矩陣

OpenGL之矩陣

OpenGL的變換運算均使用4×4矩陣進行.OpenGL使用堆棧保存矩陣.各種變換運算均針對棧頂進行操作.

矩陣 簡介
void glMatrixMode (GLenum mode); 設定當前矩陣堆棧
GL_MODELVIEW 模型視圖矩陣
GL_PROJECTION 投影矩陣
GL_COLOR 顏色矩陣
GL_TEXTURE 紋理矩陣

示例

  1. glMatrixMode(GL_MODELVIEW); 設定當前矩陣為模型視圖矩陣
  2. glLoadIdentity();載入單位矩陣,並且朝向負Z軸
  3. 進行其它變換
矩陣堆棧 簡介
void glPushMatrix(void); 複製當前矩陣(棧頂)並壓棧.
void glPopMatrix(void); 當前矩陣堆棧出棧並丟棄.

將當前坐標系統切換為新坐標系統,渲染完成後恢復原始坐標系統.示例:

  1. glMatrixMode(GL_MODELVIEW);設定模型視圖矩陣
  2. glPushMatrix();複製當前矩陣並壓棧.
  3. glLoadIdentity();載入單位矩陣
  4. glTranslatef(x,y,x);移動坐標系
  5. glPopMatrix();出棧,恢復源始坐標系統

不同矩陣堆棧有不同的深度,可通過glGetIntegerv()獲取

參數 深度 簡介
GL_MAX_MODELVIEW_STACK_DEPTH 32 模型視圖矩陣堆棧的深度
GL_MAX_PROJECTION_STACK_DEPTH 10 投影矩陣堆棧的深度
GL_MAX_TEXTURE_STACK_DEPTH 10 紋理矩陣堆棧的深度
GL_MAX_ATTRIB_STACK_DEPTH 16 屬性矩陣堆棧的深度

獲取模型視圖矩陣深度示例:

  1. GLint params[1];
  2. glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH,params);

OpenGL之旋轉

OpenGL之旋轉

旋轉glRotatef()使模形圍繞軸向量進行旋轉.先設定旋轉矩陣後繪畫模型.

旋轉 簡介
void glRotatef (

GLfloat angle,

GLfloat x,

GLfloat y,

GLfloat z);

單精度版本

angle:旋轉角度

逆時針旋轉:角度為正

順時針旋轉:角度為負

xyz:旋轉軸向量

void glRotated (

GLdouble angle,

GLdouble x,

GLdouble y,

GLdouble z);

雙精度版本

函式示例分別對XYZ進行旋轉:

  1. 設定模型視圖矩陣glMatrixMode(GL_MODELVIEW);
  2. 載入單位矩陣glLoadIdentity();
  3. 繞X軸旋轉glRotatef(angleX,1,0,0);
  4. 繞Y軸旋轉glRotatef(angleY,0,1,0);
  5. 繞Z軸旋轉glRotatef(angleZ,0,0,1);
  6. 繪畫立方體Draw();
旋轉示例 簡介
glRotatef(45.0f,1.0f,0.0f,0.0f); 繞X軸以逆時針方向旋轉45度
glRotatef(-90.0f,0.0f,1.0f,0.0f); 繞Y軸以順時針方向旋轉45度
glRotatef(135.0f,0.0f,0.0f,1.0f); 繞Z軸以逆時針方向旋轉135度

旋轉演示程式如上圖:下載

  1. 按UP/DOWN鍵繞X軸旋轉
  2. 按LEFT/RIGHT鍵繞Y軸旋轉
  3. 按Z+LEFT/Z+RIGHT鍵繞Z軸旋轉
  4. 按F1鍵打開幫助
  5. 按ESC鍵模型旋轉角度重置

OpenGL之縮放

OpenGL之縮放

縮放glScalef()可在XYZ三軸指定不同縮放系數,放大或縮小模型或坐標系統的大小.

放大: 縮放系數大於(>1),若設為2放大一倍

縮小: 縮放系數為(1.0~0.0),若設為0.5側縮小一倍

函式示例:

  1. 設定模型視圖矩陣glMatrixMode(GL_MODELVIEW);
  2. 載入單位矩陣glLoadIdentity();
  3. 縮放glScalef(x,y,z);參數xyz為縮放系數,若縮放系數为1侧不缩放.縮放操作就是乘以縮放系數.
  4. 繪畫立方體Draw();
縮放 簡介
void glScalef(

GLfloat x,

GLfloat y,

GLfloat z);

單精度版本

對模型放大一倍:

1.    縮放glScalef(2,2,2)

2.    後再繪畫Draw()

void glScaled(

GLdouble x,

GLdouble y,

GLdouble z);

雙精度版本

縮放演示程式如上圖:下載

  1. 按UP/DOWN鍵對XYZ三軸進行模型縮放
  2. 按LEFT/RIGHT鍵繞Y軸旋轉
  3. 按F1鍵打開幫助
  4. 按ESC鍵模型縮放重置

OpenGL之平移

OpenGL之平移

平移Translate可將模型在3D世界中移動,先設定平移矩陣後繪畫模型:

函式示例:

  1. 設定模型視圖矩陣glMatrixMode(GL_MODELVIEW);
  2. 載入單位矩陣glLoadIdentity();
  3. 移動3D坐標glTranslatef(x,y,z);參數xyz為3D世界坐標的偏移量
  4. 繪畫立方體Draw();
平移 簡介
void glTranslatef(

GLfloat x,

GLfloat y,

GLfloat z);

單精度版本

如在3D世界(6,6,6)繪畫模型:

1.     先平移glTranslatef(6,6,6)

2.     後在繪畫Draw()

void glTranslated(

GLdouble x,

GLdouble y,

GLdouble z);

雙精度版本

平移演示程式如上圖:下載

  1. 按LEFT/RIGHT鍵模型在X軸中移動
  2. 按UP/DOWN鍵模型在Z軸中移動
  3. 按F1鍵打開幫助
  4. 按ESC鍵模型歸位

OpenGL之投影變換

OpenGL之投影變換

投影變換是指設定視口面積和剪切平面,它在模型變換與視圖變換之後執行,用於確定那些多邊型模型位於視口之內. OpenGL支持兩類投影

投影變換(PROJECTION transformation) 簡介
透視投影

glFrustum()

gluPerspective()

用於3D世界的顯示與真實世界一樣, 多邊型模型呈現近大遠小
正交投影

glOrtho()

gluOrtho2D()

不考濾與攝影機的距離,顯示多邊型模型真實的大小,常用於CAD軟件和2D遊戲,文本顯示

 

透視投影 簡介
void gluPerspective (

GLdouble fovy,

GLdouble aspect,

GLdouble zNear,

GLdouble zFar);

直接指定視角和屏幕寬高比從而計算觀察截體.
Fovy 可視角度一般設為45度至90度
Aspect 屏幕的寬高比(Width/Height)
zNear 近端剪切面距離
zFar 遠端剪切面距離

 

透視投影 簡介
void glFrustum (

GLdouble left,

GLdouble right,

GLdouble bottom,

GLdouble top,

GLdouble zNear,

GLdouble zFar);

觀察截體的計算由近端剪切面與遠端剪切面確定
Left right bottom top 近端剪切面的範圍
zNear 近端剪切面距離
zFar 遠端剪切面距離

 

正交投影 簡介
Void glOrtho (

GLdouble left,

GLdouble right,

GLdouble bottom,

GLdouble top,

GLdouble zNear,

GLdouble zFar);

相同的模型不管與攝影機距離的遠近,其呈現的相同大小
left right bottom top 剪切面的範圍
zNear 近端剪切面距離
zFar 遠端剪切面距離

 

正交投影 簡介
void gluOrtho2D (

GLdouble left,

GLdouble right,

GLdouble bottom,

GLdouble top);

相當於glOrtho(left,right,bottom,top,-1,1);
left right bottom top 剪切面的範圍

投影示例

  1. 選擇投影矩陣堆棧glMatrixMode(GL_PROJECTION);
  2. 載入單位矩陣glLoadIdentity()
  3. 設定透視投影或正交投影

投影函式

void Set_Projection_OpenGL(bool Is3D)

{

::glViewport(0,0,OpenGL_Width,OpenGL_Height); // 重置視區尺寸

::glMatrixMode(GL_PROJECTION); // 設定投影矩陣

::glLoadIdentity();// 載入單位矩陣

if(Is3D == true) // 3D投影計算窗口尺寸比例

gluPerspective(54.0f,(GLfloat)OpenGL_Width/(GLfloat)OpenGL_Height,1.0f,1000.0f);

else  // 設為2D投影

gluOrtho2D(0, OpenGL_Width, 0, OpenGL_Height);

::glMatrixMode(GL_MODELVIEW);  // 設定模型視圖矩陣

::glLoadIdentity();// 載入單位矩陣

}

投影演示程式如上圖:下載

  1. 按P鍵在正交投影與透視投影之間切換
  2. 按S鍵切換抗鋸齒功能
  3. 按1鍵切換為黃色
  4. 按2鍵切換為綠色
  5. 按3鍵切換為紅色
  6. 按F1鍵打開幫助
  7. 按ESC鍵旋轉角度清零
  8. 按+鍵加大直線寬度
  9. 按-鍵減小直線寬度

Windows訪問鍵盤

Windows訪問鍵盤

此程式用於查閱鍵消息的虛擬代碼(Virtual Code)與按鍵狀態(Key state)如上圖:下載程式

在Windows訪問鍵盤有五種方法

  1. 接收WM_CHAR消息
  2. 接收WM_KEYDOWN消息
  3. 接收WM_KEYUP消息
  4. 調用GetAsyncKeyState()函式,需要輸入虛擬代碼(Virtual Code)
  5. DirectInput
Windows鍵盤消息 觸發條件
WM_CHAR 按下鍵盤
WM_KEYDOWN 按下鍵盤
WM_KEYUP 鬆開鍵盤
GetAsyncKeyState() 任何時候都可讀取鍵盤

 

Windows鍵盤消息 wParam lParam
WM_CHAR ASCII碼(ASCII Code) 按鍵狀態Key state
WM_KEYDOWN 虛擬代碼(Virtual Code)
WM_KEYUP

 

按鍵狀態Key state(BIT) 變量 簡介
0~15 整數 按鍵重複次數(repeat count)
16~12 整數 掃描碼(scan code)
24 bool 擴展鍵標識,若為1為該鍵為擴展鍵,如右側的ALT鍵和CTRL鍵
25~28 無使用
29 bool 若為1則ALT鍵被按下,否則為0
30 bool 前一個鍵的狀態
31 bool 若為1鍵被釋放,若為0鍵被按住.

 

OpenGL之繪畫多邊形

OpenGL之繪畫多邊形

OpenGL多邊形的演示程式如上圖:下載

  1. 按鼠標左鍵點擊繪畫多邊形,繪畫時頂點的走向為逆時針多邊形為正面,否則為背面.
  2. 按+鍵加大直線寬度
  3. 按-鍵減小直線寬度
  4. 按S鍵切換抗鋸齒功能
  5. 按.鍵切換多邊形點畫模式
  6. 按C鍵切換多邊形隱面裁剪
  7. 按1鍵填充模式
  8. 按2鍵線框模式
  9. 按3鍵頂點模式
  10. 按4鍵切換為白色
  11. 按5鍵切換為黃色
  12. 按6鍵切換為紅色
  13. 按F1鍵打開幫助
  14. 按ESC鍵清空畫面

繪畫多邊形,頂點不能小於3個

  1. glBegin(GL_POLYGON);準備繪畫多邊形
  2. for (int i = 0; i < count; ++i)
  3. glVertex3f(v[i].x,v[i].y,v[i].z);繪畫多邊形頂點
  4. glEnd();結束繪畫

多邊形其它設定請參考三角形

OpenGL之繪畫四邊形

OpenGL之繪畫四邊形

OpenGL四邊形的演示程式如上圖:下載

  1. 按鼠標左鍵點擊繪畫四邊形,繪畫時頂點的走向為逆時針四邊形為正面,否則為背面.
  2. 按+鍵加大直線寬度
  3. 按-鍵減小直線寬度
  4. 按S鍵切換抗鋸齒功能
  5. 按.鍵切換四邊形點畫模式
  6. 按C鍵切換四邊形隱面裁剪
  7. 按1鍵填充模式
  8. 按2鍵線框模式
  9. 按3鍵頂點模式
  10. 按4鍵每四個頂點組成四邊形
  11. 按5鍵頂點相連的四邊形

繪畫四邊形

  1. glBegin(GL_TRIANGLES);準備繪畫四邊形
  2. for (int i = 0; i < count; ++i)
  3. glVertex3f(v[i].x,v[i].y,v[i].z);繪畫四邊形頂點
  4. glEnd();結束繪畫
glBegin()繪畫四邊形參數 簡介
GL_QUADS 每四個頂點組成四邊形
GL_QUAD_STRIP 頂點相連的四邊形,需要把第三第四個頂點的渲染順序交換.

四邊形也屬於多邊形其它設定請參考三角形

 

OpenGL之繪畫三角形

OpenGL之繪畫三角形

OpenGL三角形屬於多邊形.演示程式如上圖:下載

  1. 按鼠標左鍵點擊繪畫三角形,繪畫時頂點的走向為逆時針三角形為正面,否則為背面.
  2. 按+鍵加大直線寬度
  3. 按-鍵減小直線寬度
  4. 按S鍵切換抗鋸齒功能
  5. 按.鍵切換三角形點畫模式
  6. 按C鍵切換三角形隱面裁剪
  7. 按1鍵填充模式
  8. 按2鍵線框模式
  9. 按3鍵頂點模式
  10. 按4鍵每三個頂點組成三角形
  11. 按5鍵頂點相連的三角形
  12. 按6鍵第一個頂點作為三角形的共同頂點

繪畫三角形

  1. glBegin(GL_TRIANGLES);準備繪畫三角形
  2. glVertex3f(x1,y1,z1);繪畫三角形頂點1
  3. glVertex3f(x2,y2,z2);繪畫三角形頂點2
  4. glVertex3f(x3,y3,z3);繪畫三角形頂點3
  5. glEnd();結束繪畫
glBegin()繪畫直線參數 簡介
GL_TRIANGLES 每三個頂點組成三角形
GL_TRIANGLE_STRIP 頂點相連的三角形
GL_TRIANGLE_FAN 第一個頂點作為三角形的共同頂點

因屏幕由像素組成,三角形邊緣會產生鋸齒,啟用抗鋸齒算法後會變得平滑,並修改邊緣像素的顏色:

  1. glEnable(GL_POLYGON_SMOOTH);啟用多邊形的平滑模式(抗鋸齒功能)
  2. glEnable(GL_BLEND);啟用混合

多邊形模式(正面默認為填充模式)

void glPolygonMode(GLenum face,GLenum mode);

多邊形面(face) 簡介
GL_FRONT 多邊形正面:頂點的走向為逆時針(默認)
GL_BACK 多邊形背面:頂點的走向為順時針
GL_FRONT_AND_BACK 正面與背面

 

多邊形模式(mode) 簡介
GL_FILL 填充模式:對多邊形內部進行顏色填充(默認)
GL_LINE 線框模式:多邊形只繪畫直先不填充
GL_POINT 頂點模式:只繪畫多邊形頂點

設置多邊形隱面裁剪

3D圖形渲染的工作量非常大,把不可見的面剔除則可節減大量變換和渲染時間.

  1. glEnable(GL_CULL_FACE);啟用隱面裁剪
  2. glCullFace(GL_BACK);設背面為隱面
  3. glFrontFace(GL_CCW);多邊形正面使用逆時針
正面模式(MODE) 簡介
GL_CCW 多邊形正面使用逆時針
GL_CW 多邊形反面使用順時針

多邊形點畫模式可用於簡單的填充(不太常用)

void glPolygonStipple(GLushort * mask);

mask:掩碼大小寬8byte*高16byte=128(byte)=1024(bit),1填充像素,0不填充

  1. glEnable(GL_POLYGON_STIPPLE);啟用點畫模式
  2. glPolygonStipple(mask);設置掩碼

 

OpenGL之繪畫直線

OpenGL之繪畫直線

OpenGL支持基本幾何直線繪畫,使用glVertex()生成繪畫相連直線的演示程式如上圖:下載

  1. 按鼠標左鍵點擊繪畫相連直線
  2. 按+鍵加大直線寬度
  3. 按-鍵減小直線寬度
  4. 按S鍵切換直線抗鋸齒功能
  5. 按.鍵切換直線點畫模式(虛線)
  6. 按1鍵切換为白色
  7. 按2鍵切換为黄色
  8. 按3鍵切換为红色
  9. 按4鍵每兩個頂點組成的直線
  10. 按5鍵由多個頂點組成的相連直線
  11. 按6鍵由多個頂點組成相連的閉合直線

繪畫直線

  1. glLineWidth(width);設置直線寬度
  2. glBegin(GL_LINE_STRIP);準備繪畫連續直線
  3. glVertex3f(x1,y1,z1);繪畫直線頂點1
  4. glVertex3f(x2,y2,z2);繪畫直線頂點2
  5. glEnd();結束繪畫
glBegin()繪畫直線參數 簡介
GL_LINES 由兩個頂點組成的直線
GL_LINE_STRIP 由多個頂點組成的相連直線
GL_LINE_LOOP 由多個頂點組成相連的閉合直線,第一個與最後一個頂點自動相連

因屏幕由像素組成,直線邊緣會產生鋸齒,OpenGL有抗鋸齒算法,啟用後直線會變得平滑,並修改邊緣像素的顏色:

  1. glEnable(GL_LINE_SMOOTH);啟用直線的平滑模式(抗鋸齒功能)
  2. glEnable(GL_BLEND);啟用混合

點畫模式通常用繪畫虛線

void glLineStipple(GLint factor,GLushort pattern);

factor:模板每BIT對應像素量

pattern:由2個Btye組成點畫模板

  1. glEnable(GL_LINE_STIPPLE);設置點畫模式(虛線)
  2. glLineStipple(5,0xfafa);設置模板

開啟直線抗鋸齒算法後,直線寬度範圍受到限制,若輸入不受支持直線寬度,會改為最接近的支持數值:

  1. GLfloat widths[2];浮點數數組
  2. glGetFloatv(GL_LINE_WIDTH_RANGE, widths);提取直線寬度的範圍
  3. GLfloat min = widths[0];最小
  4. GLfloat max = widths[1];最大
  5. GLfloat granularity;
  6. glGetFloatv(GL_LINE_WIDTH_GRANULARITY,&granularity);提取直線寬度的粒度
  7. GLfloat width;
  8. glGetFloatv(GL_LINE_WIDTH,&width);獲取當前直線寬度
  9. width = width + granularity;加大
  10. width = width – granularity;減小
  11. glPointSize(width);設置當前直線寬度,但不能在glBegin()與glEnd()之間調用

Microsoft Visual C++之鍵盤快捷鍵

Microsoft Visual C++之鍵盤快捷鍵

因為VC是最好用的基於Windwos的 C編譯器,但如果配合快捷鍵使用將會事半功倍

快捷鍵 簡介
CTRL+U 選擇文本轉為小寫
CTRL+SHIFT+U 選擇文本轉為大寫
CTRL+F Find(查找字符串),但Find In Files顯示輸出欄Output比Find更好用
CTRL+H 替換字符串,VC最好用的文本編輯工具
CTRL+C 拷貝文本
CTRL+V 粘貼文本
CTRL+Z 撤消文本
CTRL+Y 恢復文本
CTRL+A 全選文本
CTRL+R 編輯資源文檔resources.rc
CTRL+S 保存文檔,使用率最高的快捷鍵.良好使用習慣
F7 編譯所有文檔
CTRL+F7 編譯當前文檔
ALT+F7 工程設置(Project Settings)較小使用
ALT+2 顯示輸出欄Output
ALT+0 打開並把焦點切換到workspace
CTRL+W 嚮導無用
CTRL+G Go to很小使用
ATL+F2 BOOKMARKS書簽
CTRL+F2 標記
F11 單步調試
CTRL+F10 Run to cursor運行到遊標
F5 把修改項編譯並執行程式,或斷點後繼續執行,常用鍵之一.
CTRL+F5 不重新編譯只執行程式,用於編譯時長耐工程
CTRL+ SHIFT+8 View whitespace在空格加入或刪除”~”無用的工能只會讓人困惑.
CTRL+SHIFT+SPACE Parameter info查看函式的參數,最好用的快捷鍵之一
CTRL+T Type Info查看函式或變量的類型信息,最好的用快捷鍵之一
CTRL+ALT+T 自動彈出全局變量與全局函式,按::也可自動彈出,最好用的快捷鍵之一

 

WordPress之Jetpack外掛

WordPress之Jetpack外掛

終於可以成功啟用Jetpack梯來它有很強的系統依賴性,我之前是Godaddy的Windows的主機,我把所有舊版Jetpack都嘗試安裝無一成功,後更改為Linux主機後成功安裝. Jetpack是Wordpress的十全大補外掛,因此我刪除左三個重複外掛!你需要wordpress.com的帳號但很多服務需要收費,有點點雞肋的感覺.

Jetpack提供 簡介
分享按扭 安裝Jetpack的原因之一,第三方分享按扭大多如人意,而且大多經過跳轉.
第三方帳號登錄 安裝Jetpack的最大誘因,允許使用WordPress.com、Twitter、Facebook 或 Google+帳號登錄
自動分享 本人認為手動分享更零活
點贊按扭 對於Blog意義不大
相關文章 Contextual Related Posts選項更多

Jetpack只可顯示三個相關文章,意義不大.

網誌統計 流量統計分析與感覺一般,可以整合Google Analytics但需要收費.
廣告ADS 廣告需要收費暈
文章摘要 Jetpack支持文章摘要,但只支持移動主題.
SEO 暈又收費
網站地圖 XML自動傳送至所有主要搜尋引擎進行索引。Wordpress本已內置同步訂閱,而且更好用.
聯繫表單 意見反應,有一定作用,但可使用迴響替代.
短網址 短網址對於Blog意義不大
電郵發表文章 智能手機時代意義不大
留言Markdown 文本標記語言
留言點贊 有一定意義
大頭貼 無用過
惡意登入 主動阻擋惡意登入嘗試
備份 自動備份整個網站,收費
停機監控 郵件通知
無限捲動 手機移動閱覽時效果

 

OpenGL之繪畫頂點

OpenGL之繪畫頂點

OpenGL支持基本幾何頂點繪畫,使用glVertex()生成畫點的演示程式如上圖:下載

  1. 按鼠標左鍵繪畫頂點
  2. 按+鍵加大頂點尺寸
  3. 按-鍵減小頂點尺寸
  4. 按S鍵切換抗鋸齒功能
  5. 按1鍵切換為白色
  6. 按2鍵切換為黃色
  7. 按3鍵切換為紅色

繪畫單個頂點

  1. glPointSize(size);設置頂點的大小
  2. glBegin(GL_POINTS); 準備繪畫
  3. glVertex3f(x,y,z); 繪畫頂點(浮點數版)
  4. glVertex3i(x,y,z); 繪畫頂點(整數版)
  5. glEnd(); 結束繪畫

因屏幕由像素組成,縮放頂點時邊緣會產生鋸齒,OpenGL有其抗鋸齒算法,啟用後頂定會由方變圓,並修改邊緣像素的顏色:

if (glIsEnabled(GL_POINT_SMOOTH) == false)// 判斷抗鋸齒是否已啟用

{

glEnable(GL_POINT_SMOOTH); // 啟用頂點的平滑模式(抗鋸齒功能)

glEnable(GL_BLEND);// 需啟用混合

}

開啟抗鋸齒算法後,頂點尺寸範圍受到限制,若輸入不受支持頂點的尺寸,會改為最接近的支持數值:

  1. GLfloat sizes[2];浮點數數組
  2. glGetFloatv(GL_POINT_SIZE_RANGE,sizes);提取頂點尺寸的範圍
  3. GLfloat min = sizes[0];最小
  4. GLfloat max = sizes[1];最大
  5. GLfloat granularity;
  6. glGetFloatv(GL_POINT_SIZE_GRANULARITY,&granularity);提取頂點尺寸的粒度
  7. GLfloat size;
  8. glGetFloatv(GL_POINT_SIZE,&size);獲取當前頂點尺寸
  9. size = size + granularity;加大
  • size = size – granularity;減小
  • glPointSize(size);設置當前頂點的大小,但不能在glBegin()與glEnd()之間調用

OpenGL之速度與質量

OpenGL之速度與質量

因顯卡性能各異,所以OpenGL可給用戶在速度與質量之間作出選擇,參數在下表給出.並給出示例代碼:

Void glHint(GLenum target, GLenum hint);

HINT 簡介
GL_FASTEST 使用最快速度和效率,但畫面質量有所下降.
GL_NICEST 使用最高畫面質量,但運行速度有所下降
GL_DONT_CARE 由顯卡的OpenGL驅動在速度和質量之間作出選擇

 

TARGET 簡介
GL_POINT_SMOOTH_HINT 指定在進行反鋸齒的操作中,點、線、多邊形的抽樣質量
GL_LINE_SMOOTH_HINT
GL_POLYGON_SMOOTH_HINT
GL_FOG_HINT 若hint設為GL_NICEST,煙霧的計算將以每像素的形式執行

若hint設為GL_FASTEST,煙霧的計算將以每頂點的形式執行

GL_PERSPECTIVE_CORRECTION_HINT 指定顏色和紋理坐標的插值品質

設置OpenGL性能

hint:建議性能

GL_FASTEST:速度優先

GL_NICEST:最高畫面質量

GL_DONT_CARE:由顯卡驅動決定

void Set_Hint_OpenGL(GLenum hint)

{

glHint(GL_POINT_SMOOTH_HINT,          hint);// 點

glHint(GL_LINE_SMOOTH_HINT,           hint);// 線

glHint(GL_POLYGON_SMOOTH_HINT,        hint);// 多邊形

glHint(GL_FOG_HINT,                   hint);// 煙霧

glHint(GL_PERSPECTIVE_CORRECTION_HINT,hint);//紋理坐標

}

OpenGL之錯誤碼

OpenGL之錯誤碼

OpenGL內部有ERROR錯誤標記,若向OpenGL的函式傳遞不正確的參數,函式會設置錯誤碼並返回.錯誤代碼一但產生就不會修改,直到調用

GLenum error = glGetError();

它將返回下表的錯誤代碼,並把標記重設為GL_NO_ERROR:

錯誤碼 簡介
GL_NO_ERROR 無錯誤
GL_INVALID_ENUM 傳遞不被支持枚舉型(enum)數值時產生此錯誤
GL_INVALID_VALUE 傳遞超出可接受範圍的數值時產生此錯誤
GL_INVALID_OPERATION 傳遞參數未能運行或當前設置未能運行,這錯誤碼較上兩者更難以追查錯誤
GL_STACK_OVERFLOW 堆盞溢出
GL_STACK_UNDERFLOW 堆盞不平衡
GL_OUT_OF_MEMORY 內存耗盡或內存洩漏
GL_TABLE_TOO_LARCE 過多使用TABLE而產生

 

OpenGL版本

OpenGL之查詢版本

調用glGetString()可以很方便提取顯卡的OpenGL信息,但需在wglMakeCurrent()之後調用,否則返回NULL.我使用此函式製作讀取OpenGL版本程式:下載

函式原型:

const GLubyte * glGetString(GLenum name);

name參數 簡介
GL_VENDOR 顯卡的製造商名稱
GL_RENDERER 顯卡型號和CPU的信息
GL_VERSION 顯卡驅動主輔版本號
GL_EXTENSIONS OpenGL擴展支持列表,以空格進行分割

 

OpenGL之全屏

OpenGL之全屏

從DOS,街機到手機遊戲都是以全屏出現,全屏顯示只需加入小量代碼

  1. 填充DEVMODE數據結構
  2. 設定屏幕寬度dmPelsWidth
  3. 設定屏幕高度dmPelsHeight
  4. 設定屏幕像素BIT數dmBitsPerPel
  5. 設定有效字dmFields
  6. 調用ChangeDisplaySettings(&devmode,CDS_FULLSCREEN)進入全屏模式,成功設定返回DISP_CHANGE_SUCCESSFUL
  7. 創建窗口CreateWindowEx()
  8. 擴展樣式設為全屏窗口WS_EX_APPWINDOW
  9. 窗口樣式樣式設為無邊框窗口WS_POPUP
  10. 窗口寬高需等於屏幕寬高
  11. 隱藏鼠標ShowCursor(false);

設定為全屏需在CreateWindow之前調用,下面是完整的代碼

bool Set_FullScreen_OpenGL(int screenWidth,int screenHeight,int screenBpp )

{

DEVMODE devmode;

memset(&devmode,0,sizeof(devmode));// 清零

devmode.dmSize = sizeof(DEVMODE);// 填充DEVMODE

devmode.dmPelsWidth  = screenWidth;// 屏幕寬度

devmode.dmPelsHeight = screenHeight;// 屏幕高度

devmode.dmBitsPerPel = screenBpp;// 屏幕像素BIT數

devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;// 設定有效字段

// 設為全屏

if(ChangeDisplaySettings(&devmode,CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL)

OpenGL_FullScreen = true;

else

OpenGL_FullScreen = false;

return OpenGL_FullScreen;

}

退出程序時恢復為窗口模式

bool Set_Window_OpenGL()

{ // 設為窗口模式

if(ChangeDisplaySettings(NULL,0) == DISP_CHANGE_SUCCESSFUL)

{

OpenGL_FullScreen = false;

ShowCursor(true);// 顯示鼠標

}

return OpenGL_FullScreen;

}

OpenGL之重設窗口大小

OpenGL之重設窗口大小

當OpenGL窗口的大小發生改變時,OpenGL窗口會變形需要重新設定以適應新的窗口大小.

  1. 收到WM_SIZE消息後獲取窗口大小,高度為HIWORD(lParam),寬度為LOWORD(lparam)
  2. 重置視區尺寸glViewport(0,0,width,height);
  3. 設定投影矩陣glMatrixMode(GL_PROJECTION);
  4. 載入單位矩陣glLoadIdentity();
  5. 計算窗口尺寸比例gluPerspective();
  6. 設定模型視圖矩陣glMatrixMode(GL_MODELVIEW);
  7. 載入單位矩陣glLoadIdentity();

給出重設窗口大小完整代碼

void Set_WindowSize_OpenGL(int width,int height)

{

if(height == 0)

height = 1;// 确保分母不为0

// 重置视区尺寸

::glViewport(0,0,width,height);

// 设定投影矩阵

::glMatrixMode(GL_PROJECTION);

// 载入单位矩阵

::glLoadIdentity();

// 计算窗口尺寸比例

gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,1.0f,1000.0f);

// 设定模型视图矩阵

::glMatrixMode(GL_MODELVIEW);

// 载入单位矩阵

::glLoadIdentity();

}

OpenGL之繪製環境

OpenGL之繪製環境

繪製環境Context用於記錄OpenGL的設置和命令,但繪製環境必需在像素格式設置完成後調用.下麵是簡介和源碼

繪製環境 簡介
HGLRC 繪製環境的句柄
HGLRC wglCreateContext(HDC hDC); 創建繪製環境,並返回繪製環境句柄, 在WM_CREATE消息下調用
BOOL wglDeleteContext(HDC hDC,HGLRC hRC); 刪除繪製環境, 在WM_CLOSE消息下調用
BOOL wglMakeCurrent(HDC hDC,HGLRC hRC); 設置當前繪製環境,若HGLRC設為NULL則取消當前設定的繪製環境

創建繪製環境

void Create_Context_OpenGL(HDC hDC)

{ //創建繪製環境

hGLRC = ::wglCreateContext(hDC);

// 設置為繪製環境

::wglMakeCurrent(hDC,hGLRC);

}

刪除繪製環境

void Delete_Context_OpenGL(HDC hDC)

{ // 取消設定的為繪製環境

::wglMakeCurrent(hDC,NULL);

// 刪除繪製環境

::wglDeleteContext(hGLRC);

}

OpenGL之像素格式

OpenGL之像素格式

在OpenGL工作之前需要設定當前環境設備(顯卡)像素格式,只需三步:

設定像素格式 簡介
PIXELFORMATDESCRIPTOR 填充像素格式
ChoosePixelFormat() 獲取顯卡支持的像素格式,返回索引
SetPixelFormat() 設置當前環境設備(顯卡)的像素格式

PIXELFORMATDESCRIPTOR需要填補的數值較多

字段 填充數值 像素格式簡介
iPixelType sizeof(PIXELFORMATDESCRIPTOR) 結構的大小
nVersion 1 版本號填1
dwFlags PFD_DRAW_TO_WINDOW 支持在窗口繪畫
PFD_DRAW_TO_BITMAP 支持在位圖繪畫
PFD_SUPPORT_GDI 緩存支持GUI繪畫
PFD_SUPPORT_OPENGL 緩存支持OPENGL繪畫
PFD_GENERIC_ACCELERATED
PFD_GENERIC_FORMAT
PFD_NEED_PALETTE
PFD_NEED_SYSTEM_PALETTE
PFD_DOUBLEBUFFER 支持雙緩存
PFD_STEREO
PFD_SWAP_LAYER_BUFFERS 支持交換Layer緩存
PFD_DEPTH_DONTCARE 支持Z緩存
PFD_DOUBLEBUFFER_DONTCARE
PFD_STEREO_DONTCARE
iPixelType PFD_TYPE_RGBA RGBA像素
PFD_TYPE_COLORINDEX 256色使用調色板索引
cColorBits 32、24、16、8 每像素所占字節數
cRedBits 0 紅色所占Bit數
cRedShift 0 紅色偏移Bit量
cGreenBits 0 綠色所占Bit數
cGreenShift 0 綠色偏移Bit量
cBlueBits 0 藍色所占Bit數
cBlueShift 0 藍色偏移Bit量
cAlphaBits 0 Alpha所占Bit數
cAlphaShift 0 Alpha偏移Bit量
cAccumBits 0 累加緩存Bit數
cAccumRedBits 0 紅色累加緩存Bit數
cAccumGreenBits 0 綠色累加緩存Bit數
cAccumBlueBits 0 藍色累加緩存Bit數
cAccumAlphaBits 0 Alpha累加緩存Bit數
cDepthBits 16 z-buffer(Z緩存)大小
cStencilBits 0 模板緩存Bit數
cAuxBuffers 0 輔助緩存Bit數
iLayerType 0 繪製平面
bReserved 0 保留字段
dwLayerMask 0 不在使用
dwVisibleMask 0 透明色掩碼索引
dwDamageMask 0 不在使用

 

最後給出完整代碼

void Setup_PixelFormat_OpenGL(HDC hDC)

{

PIXELFORMATDESCRIPTOR pfd;

int index;

pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);// 結構的大小

pfd.nVersion = 1;//版本號填1

pfd.dwFlags  = PFD_DRAW_TO_WINDOW |//  支持窗口

PFD_SUPPORT_OPENGL |// 支持OPENGL

PFD_DOUBLEBUFFER   ;// 支持雙緩存

pfd.iPixelType = PFD_TYPE_RGBA;// 像素數據類型RGBA

pfd.cColorBits = 16;// 16bit每像素所占字節數

pfd.cRedBits   = 0;// 紅色所占Bit數

pfd.cRedShift  = 0;// 紅色偏移Bit量

pfd.cGreenBits   = 0;// 綠色所占Bit數

pfd.cGreenShift  = 0;// 綠色偏移Bit量

pfd.cBlueBits   = 0;// 藍色所占Bit數

pfd.cBlueShift  = 0;// 藍色偏移Bit量

pfd.cAlphaBits  = 0;// Alpha所占Bit數

pfd.cAlphaShift  = 0;// Alpha偏移Bit量

pfd.cAccumBits      = 0;// 累加緩存Bit數

pfd.cAccumRedBits   = 0;// 紅色累加緩存Bit數

pfd.cAccumGreenBits = 0;// 綠色累加緩存Bit數

pfd.cAccumBlueBits  = 0;// 藍色累加緩存Bit數

pfd.cAccumAlphaBits = 0;// Alpha累加緩存Bit數

pfd.cDepthBits      = 16;// 16bit z-buffer(Z緩存)大小

pfd.cStencilBits    = 0;// 模板緩存Bit數

pfd.cAuxBuffers     = 0;// 輔助緩存Bit數

pfd.iLayerType      = 0;// 無繪製平面

pfd.bReserved       = 0;// 保留字段

pfd.dwLayerMask     = 0;// 不在使用

pfd.dwVisibleMask   = 0;// 透明色掩碼索引

pfd.dwDamageMask    = 0;// 不再使用了

// 獲取當前環境設備(顯卡)支持的像素格式,返回索引

index = ::ChoosePixelFormat(hDC,&pfd);

// 設置當前環境設備(顯卡)的像素格式

::SetPixelFormat(hDC,index,&pfd);

}

OpenGL簡介

OpenGL簡介

在DOS時代因為當時硬件品類小,程序直接控制硬件,但當硬件品類不斷增加,要對所有硬件進行支持變得不現實.所以便有OpenGL的出現,把硬件的支持交還給硬件開發商.

最初OpenGL由Silicon Graphics,Inc(SGI)開發的一個可以跨平臺使用的圖形編程接口, GL就是Graphics library的縮寫,最初用於UNIX工作站.

1992年OpenGL Architecture Review Board(ARB)委員會創建,由ATI,Compaq,Evans&Sutherland,Hewlett-packard,IBM,Intel,Intergraph,Nvidia,Microsoft,Silicon Graphics組成

1995年微軟在遊戲廠商進逼下不得已在WinNT中支持OpenGL

程式庫 簡介 下載點
OpenGL 標準OpenGL 下載1下載2
GLU (實用庫)OpenGL的補充

 

GLUT (OpenGL Utility Toolkit)應用工具包,與系統無關且便於移於移植.作為AUX庫的的替代品.

 

下載

 

下載並解壓後,更據文檔的擴展名拷貝到各自對應的VC目錄

文件 文檔類形 目錄
include files .h文檔 C:\Program Files\Microsoft Visual Studio\VC98\Include\GL
Library files .lib文檔 C:\Program Files\Microsoft Visual Studio\VC98\Lib
Executable files .dll文檔 C:\Program Files\Microsoft Visual Studio\VC98\Bin

 

程式頭文檔 程式庫文檔 程式二進制文檔 簡介
gl.h Opengl32.lib OPENGL32.DLL 標準OpenGL頭文件
glu.h Glu32.lib GLU32.DLL OpenGL實用工具庫
glaux.h GLAUX.LIB OpenGL輔助函數庫
glut.h glut.lib glut.dll OpenGL應用工具包
glut32.lib glut32.dll

 

DIY打印絕版書

DIY打印絕版書
DIY打印絕版書

對於愛書之人最疼心的你愛的書已絕版無緣一讀.但如果作者公開左它的(電子版)PDF文檔,則你還有一線希望,但電子版是無法替代紙質版(如果你真正讀書).下面將教你如何打印整本書

  1. 準備A4打印紙(Double A)
  2. 打印機最好支持正反面打印,否則要奇偶頁分開打印
  3. 介質選”普通紙”.
  4. 打印質量選”標準”.
  5. 頁面縮放方式選”適合可打印區域”
  6. 我只使用黑色墨盒,在打印前先加墨.
  7. 打印後用木板輕拍對齊所有紙張
  8. 放一張空白A4紙在書面,在左側畫四個鑽孔坐標,繪畫距離邊為10MM的直線,在上下兩邊距15MM繪畫兩條交線,在中間距離6MM畫兩條交線(如上圖).
  9. 鋼夾一個到兩個,用於夾緊所有A4紙
  10. 台鑽一台,2MM鑽嘴一支.
  11. 長針一支長約90MM
  12. 轉一個孔就紮一條線,四個孔分別紮.
  13. 再對四個孔穿插紮線.
  14. 封皮請勿使用毛巾

佳能打印機5200錯誤碼

佳能打印機5200錯誤碼
佳能打印機5200錯誤碼

Canon打印機5200錯誤碼是指墨頭的溫度過高,報警燈不停的閃,提示關閉打印機後重啟.通常是沒有墨水導致的,可能是之前墨盒鑽孔無轉穿,墨水無滲透如海綿,令墨水枯乾損壞墨頭, 打印頭噴嘴出現堵塞,大面積打印就出現5200錯誤碼,最後只能更換墨盒解決!!!

記注墨盒一定不能幹透會損壞墨盒!

URL編解碼器

URL編解碼器

URL連接只支持ASCII碼進行傳送,若要傳送非ASCII碼則需進行編碼.很多時因網絡問題,需要進行URL編碼與解碼.所以便製作URL編解碼器.代碼是我在2010寫的下載軟件移植過來.支持下列類型編解碼

類型 簡介
thunder 迅雷
flashget 快車
qqdl QQ旋風
Binary 所有代碼進行編碼
http 標準編碼
ALL 對\ : & =進行編碼

Win32版下載

Windows之設置EDITTEXT為只讀模式

Windows之設置EDITTEXT為只讀模式

近日需要把文本輸入框(EDITTEXT)設為不可編輯,也就是只讀模式.發現在Dialog下無法啟用,並且在WM_INITDIALOG設置STYLE也無作用.下面給出設置方法:

  1. HWND hWnd = CreateDialog();創建Dialog後
  2. hWnd hEdit= ::GetDlgItem(hWnd,IDDEIT);
  3. SendMessage(hEdit,EM_SETREADONLY,true,0);
  4. WPARAM設為TRUE則啟用只讀模式,設為FALSE則啟用編輯模式

Windows文件拖放

Windows文件拖放

近日要實現文件拖放,如果只實現接收則較為簡單,下麵把實現原理記下.

  1. 令主窗口可以接受文件拖放::DragAcceptFiles(hWnd,TRUE);
  2. 處理WM_DROPFILES消息wParam為HDROP文件拖放句柄
  3. 獲取拖放文件的個數::DragQueryFile(hdrop,-1,NULL,0);
  4. 獲取拖放文件的路徑DragQueryFile(hdrop,File_Index,File_Path,sizeof(File_Path));
  5. 處理拖放文件File_Path
  6. 重複第四第五步提取拖放文件的路徑
  7. 釋放拖放空間::DragFinish(hdrop);

 

int Query_DragAndDrop(HDROP  hdrop,PROC_DRAGANDDROP Proc_DragAndDrop)

{

int  File_Num;

TCHAR File_Path[2056];

int  File_Index;

File_Num = ::DragQueryFile(hdrop,-1,NULL,0);// 獲取文件個數

for(File_Index = 0; File_Index < File_Num; ++File_Index)

{ // 獲取拖放文件

::DragQueryFile(hdrop,File_Index,File_Path,sizeof(File_Path));

Proc_DragAndDrop(File_Path);// 處理文件

}

::DragFinish(hdrop);// 釋放空間

return 1;

}

HASH校驗器

HASH校驗器

HASH(哈希碼)用於生成文件的指紋,如果兩個文件的哈希碼一致,則代表文件是相同的.令外也用於生成密碼指紋.此軟件用於生成文件的哈希碼,支持SHA1,SHA256,SHA384,SHA512,MD5,MD4,MD2,CRC32,CRC64.大部分的哈希校驗碼是我在2009年所寫.所以此軟件製作較順利.加入文件拖放和拷貝剪貼板,全部使用純C代碼所寫速度快,體積小.

Win32版下載:HASH

 

Windows設置按扭圖標

Windows設置按扭圖標

按扭BUTTON可以設定圖標,但有幾點需要需注意:

  1. 準備一張ICO圖標
  2. 在你VC工程目標下創建ICON文件夾,把ICO圖標複製於此.
  3. 把ICO圖標編譯進程序,在RC文件加上IDR_LOGO ICON        “ICO\\logo.ico”
  4. 按扭BUTTON樣式style需加上BS_ICON
  5. 獲取應用實例句柄HMODULE hModule = ::GetModuleHandle(0);
  6. 獲取ICON圖標句柄HICON hIcon = ::LoadIcon(hModule,_T(”IDR_LOGO”));
  7. 設置按扭圖標::SendMessage(hWnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);

SEO外鏈蜘蛛

SEO外鏈蜘蛛

外鏈即指向您的網站的連結,它確定你從搜索引擎獲得多小流量.但要獲得大量的外鏈並不容易,而對於個人Blog(博客)應把精力集中于文章的質量而不是把精力用於增加外鏈.但個人博客主可以通過域名查詢網站增加外鏈,通過查詢域名流下查詢記錄,並產生一條指向你域名鏈接,而域名查詢網站首頁也會產生最新查詢鏈接,如果搜索引擎剛好來訪,你的外鏈就會增加.但天天查詢網站域名更會耗費大量精力,不過你可以製作全自動化域名查詢蜘蛛.下麵給出軟件的製作思路.

  1. 把域名查詢網站保存於文本數據庫
  2. 在圖形界面放置ComboBox下拉文本輸入框,用於輸入域名.
  3. 域名前面不加”HTTP://”後面不添加”/”
  4. 獲取默認瀏覽器路徑
  5. 創建新的線程_beginthread()
  6. 讀取一條記錄fgets()
  7. 啟動瀏覽器並打開網頁
  8. 等待30秒
  9. 關閉瀏覽器
  10. 重複第6至9步

Windows對話框圖標

Windows對話框圖標

對話框圖標在模板中不能設置,需要

1.       準備一張512×512圖片

2.       使用IconWorkshop轉換成ICO圖標

3.       分辯率勾選48×48,32×32,24×24,16×16,位數32Bit(RGBA),16Bit,8Bit(256色)即可.

4.       在你VC工程目標下創建ICON文件夾,把ICO圖標複製於此.

5.       在RSOURCE.RC文件加上,要注意第一條記錄也是應用圖標

IDR_MAINFRAME     ICON        “ICO\\logo.ico”

6.       在對話框WM_INITDIALOG設置

HICON hIcon = LoadIcon(main_instance,_T(“IDR_MAINFRAME”));//載入圖標

::SendMessage(hWnd, WM_SETICON, true, (LPARAM)hIcon);//設置大圖標

::SendMessage(hWnd, WM_SETICON, false, (LPARAM)hIcon);//設置小圖標

Windows輕量級文本數據庫

Windows輕量級文本數據庫

如果程式需要讀取大量數據可使用SQLite3關係數據庫,但如果只是讀寫小量文本數據,則使用文本一行行地保存文本更方便,擴展名最好改為.db下麵給設計思路.

讀取文本數據

  1. 以文本只讀方式打開文件_wfopen(),使用寬字符版路徑帶有中文也可打開,
  2. 讀取一行文本fgets()並進行處理
  3. 循環第二步,如返回NULL則讀取完畢.
  4. 關閉文件句柄fclose()

寫入文本數據

  1. 以文本寫入方式打開文件_wfopen(),模式使用w代表文件長度清零,否則使用a在文件尾寫入數據
  2. 寫入一行文本fputs()
  3. 寫入換行fputs(“\n”,stream);
  4. 循環第二第三步,如返回NULL則讀取完畢.
  5. 關閉文件句柄fclose()

 

讀取文本的C代碼

bool Read_DB()

{

FILE * stream=NULL; // 文件流句柄

char text[2056];

stream = _wfopen(L”text.dat”,L”r+t”);// 以文本方式打開文件

if(stream == NULL)

return false;// 無法打開文件

// 讀取一行

while(fgets(text,sizeof(text),stream) != NULL)

{  //去除字符串中最後面 “換行符”  “空格”

TrimRight(text);

// 處理文本

// ……….

}

fclose(stream); // 關閉文件句柄

return true;

}

追加一行文本的C代碼

bool Save_DB(char * text)

{

FILE * stream=NULL; // 文件流句柄

// 以文本方式打開文件

stream = _wfopen(L”text.dat”,L”a+t”);

if(stream == NULL)

return false;// 無法打開文件

::fputs(text,stream);// 寫入數據

::fputs(“\n”,stream);// 換行

fclose(stream);// 關閉文件句柄

return true;

}

Windows對話框在屏幕居中顯示

Windows對話框在屏幕居中顯示

對話框(DIALOG)模板可以設定顯示位置,但因屏幕大小不一,總想讓對話框在屏幕居中顯示.

  1. 獲取窗口的矩形區域GetWindowRect(),計算窗口的寬和高
  2. 獲取屏幕寬和高GetSystemMetrics()
  3. 重新設置窗口位置

下面給出C源代碼便於移值到其它工程

bool CentreWindow(HWND hWnd)

{

RECT rect;

int width,height;

int x,y;

if(IsWindow(hWnd) == false)

return false;

::GetWindowRect(hWnd,&rect); // 獲取窗口的

width  = rect.right – rect.left; // 計算窗口寬度

height = rect.bottom – rect.top; // 計算窗口高度

x = GetSystemMetrics(SM_CXSCREEN)/2-width/2;// 計算窗口居中X

y = GetSystemMetrics(SM_CYSCREEN)/2-height/2;// 計算窗口居中Y

SetWindowPos(hWnd,HWND_TOP,x,y,0,0,SWP_NOSIZE);  // 移動窗口

return true;

}

Windows啟動瀏覽器並打開網頁

Windows啟動瀏覽器並打開網頁

啟動瀏覽器最簡單的方法是使用ShellExecute(),但無返回進程句炳,要關閉瀏覽器只能查找窗口.更好的方法是CreateProcess()啟動瀏覽器新進程並打帶網頁,並返回進程句柄,方便關閉瀏覽器.

BOOL CreateProcess(LPCTSTR lpApplicationName,//執行模塊名填空NULL即可

LPTSTR  lpCommandLine,//命令行填”瀏覽器Path+空格+網頁URL”

LPSECURITY_ATTRIBUTES lpProcessAttributes,//進程屬性  LPSECURITY_ATTRIBUTES lpThreadAttributes,//線程屬性

BOOL bInheritHandles,  //繼承進程句柄false

DWORD dwCreationFlags, //創建標誌填CREATE_NEW_CONSOLE

LPVOID lpEnvironment, //進程環境

LPCTSTR lpCurrentDirectory,// 進程的工作路徑填NULL

LPSTARTUPINFO lpStartupInfo, //STARTUPINFO結構

LPPROCESS_INFORMATION lpProcessInformation//PROCESS_INFORMATION結構

);

  1. 要注意的是命令行lpCommandLine:瀏覽器Path+空格+網頁URL
  2. 命令行最好使用寬字符Unicode否則路徑有漢字或非ASCII碼則無法運行
  3. 返回不為false則調用成功
  4. 保存lpProcessInformation返回瀏覽器新進柄

 

下麵給打開網頁源代碼,便於

bool Open_Url(char * url,char * browser_Path)

{

int result = 0;

char CommandA[2056];

WCHAR CommandW[2056];

int length;

SECURITY_ATTRIBUTES Security_Attributes_Process;// 進程屬性

SECURITY_ATTRIBUTES Security_Attributes_Thread;// 線程屬性

STARTUPINFO        Startup_Info;// 啟動信息

PROCESS_INFORMATION Process_Information;//  進程信息

strcpy(CommandA,browser_Path);

strcat(CommandA,” “);

strcat(CommandA,url);

// 轉換UNICODE

length = MultiByteToWideChar(CP_ACP, NULL, CommandA, strlen(CommandA), CommandW, sizeof(CommandW));

CommandW[length] = NULL;

// 進程屬性

Security_Attributes_Process.nLength              = sizeof(SECURITY_ATTRIBUTES);

Security_Attributes_Process.lpSecurityDescriptor = NULL;

Security_Attributes_Process.bInheritHandle       = true;

// 線程屬性

Security_Attributes_Thread.nLength               = sizeof(SECURITY_ATTRIBUTES);

Security_Attributes_Thread.lpSecurityDescriptor  = NULL;

Security_Attributes_Thread.bInheritHandle        = true;

// 啟動信息

ZeroMemory( &Startup_Info, sizeof(STARTUPINFO) );

Startup_Info.cb = sizeof(STARTUPINFO);

ZeroMemory( &Process_Information, sizeof(PROCESS_INFORMATION) );

// 創建進程

result = CreateProcessW(NULL,

CommandW,

&Security_Attributes_Process,

&Security_Attributes_Thread,

FALSE,

CREATE_NEW_CONSOLE,

NULL,

NULL,

&Startup_Info,

&Process_Information);

// 獲取進程句柄

if(result != 0)

return true;

else

return false;

}

Windows 默認瀏覽器路徑

Windows 默認瀏覽器路徑

Windows默認瀏覽器的路徑在註冊表(REGEDIT.EXE)的HKEY_CLASSES_ROOT\http\shell\open\command\,提取數據需要使用下面三個註冊表操作函數.並給出設計思路源碼

  1. 打開註冊表句柄RegOpenKeyEx()
  2. 提取數據RegQueryValueEx()
  3. 關閉註冊表句柄RegCloseKey()
  4. 提取在雙引號中的瀏覽器路徑

 

char   Browser_Path[2056];// 瀏覽器路徑

// ————————————————————–

// 獲取系統默認瀏覽器路徑

// ————————————————————–

char * Get_WebBrowserPath_SEO(void)

{

long ret;

HKEY hKey;// 註冊表句柄

WCHAR path[2056];//

char  data[2056];

DWORD length;

// 打開註冊表

// HKEY_CLASSES_ROOT\http\shell\open\command

ret = RegOpenKeyExW(HKEY_CLASSES_ROOT,L”http\\shell\\open\\command”,0,KEY_ALL_ACCESS,&hKey);

if(ret != ERROR_SUCCESS)

return NULL;

// 獲取REG_SZ

DWORD type = REG_SZ;//類型

length = sizeof(path);//

ret = RegQueryValueExW(hKey,NULL,NULL,&type,(PBYTE)path,&length);

if(ret != ERROR_SUCCESS)

return NULL;

// 關閉註冊表句柄

RegCloseKey(hKey);

// 轉換為UTF-8

length  = WideCharToMultiByte(CP_UTF8, NULL, path, wcslen(path), data, sizeof(data), NULL, NULL);

data[length] = NULL;

// 清零

memset(Browser_Path,0,sizeof(Browser_Path));

// 提取路徑

for(int i = 0,index = 0;i<(int)length; ++i)

{

if(data[i] == ‘”‘ && index != 0)

break;// 讀取完畢跳出

if(data[i] != ‘”‘)

{

Browser_Path[index] = data[i];

++index;

}

}

return Browser_Path;// 返回路徑

}

Windows之ANSI和UNICODE與UTF8相互轉換

Windows之ANSI和UNICODE與UTF8相互轉換

因為Windows控件全部使用UNICODE編碼字符(或ANSI),而我文人卻喜歡使用UTF8編碼字符,所以需要在UTF8與UNICODE之間相互轉換,而我在2010年12月7日寫的一個字符轉換函式庫剛好派上用場.所有轉換MultiByteToWideChar()與WideCharToMultiByte()兩個函式完成,轉換後以NULL字符結尾.特將其簡化並記錄如下,便於以後移植使用.

多字節字符(ANSI/UTF-8)轉換寬字符(UNICODE)

int MultiByteToWideChar(

UINT CodePage,         // 代碼頁

DWORD dwFlags,         // 字符標誌, 默認設為0

LPCSTR lpMultiByteStr, //多字節字符

int cchMultiByte,      //多字節字符個數

LPWSTR lpWideCharStr,  // 寬字符輸出緩存

int cchWideChar        //寬字符緩存大小

);

寬字符(UNICODE)轉換多字節字符(ANSI/UTF-8)

int WideCharToMultiByte(

UINT CodePage,         //代碼頁

DWORD dwFlags,         // 字符標誌, 默認設為0

LPCWSTR lpWideCharStr, // 寬字符

int cchWideChar,       //寬字符長度

LPSTR lpMultiByteStr,  //多字節字符輸出緩存

int cchMultiByte,      //多字節字符緩存輸出大小

LPCSTR lpDefaultChar,  // 自定義寬字符,默認設為NULL

LPBOOL lpUsedDefaultChar   // 是否使用寬字符

);

//——————————————————————

// Ansi轉換Unicode

// Unicode:Unicode碼文本輸出

// Unicode_Size:Unicode碼輸出緩衝區WORD的長度

// Ansi:ANSI碼文本輸入,以NULL字符接尾

// Encode:ANSI文本字符編碼

// 返回值:Unicode 字符個數!(Unicode一個字符需兩個字節)

//——————————————————————

int Ansi_To_Unicode(WCHAR * Unicode,int Unicode_Size,char * Ansi,int Encode)

{

int Unicode_Length;// Unicode 字符個數!非字節數!

if(Unicode == NULL || Ansi == NULL)

return 0;

// Ansi轉換Unicode

Unicode_Length = MultiByteToWideChar(Encode, NULL, Ansi,strlen(Ansi), Unicode, Unicode_Size);// 轉換

Unicode[Unicode_Length] = 0;

return Unicode_Length;

}

 

//——————————————————————

//Unicode轉換Ansi

//Ansi:ANSI碼文本輸出

//Unicode_Size:Unicode碼輸出緩衝區WORD的長度

//Unicode:Unicode碼文本輸入

//返回值:Ansi所占字節數!

//——————————————————————

int Unicode_To_Ansi(char* Ansi,int Ansi_Size,PWORD Unicode)

{

int Ansi_Length;

if(Ansi == NULL || Unicode == 0)

return 0;

//Unicode轉換Ansi

Ansi_Length = WideCharToMultiByte(CP_ACP, NULL, Unicode, wcslen(Unicode), Ansi, Ansi_Size, NULL, NULL);

Ansi[Ansi_Length] = NULL;

return Ansi_Length;

}

 

//——————————————————————

// UTF-8 轉 Unicode

//Unicode:Unicode碼文本輸出

//Unicode_Size:Unicode碼輸出緩衝區WORD的長度

//Utf8:Utf-8文本輸入

//返回值:UTF-8字符個數!

//——————————————————————

int Utf8_To_Unicode(WCHAR * Unicode,int Unicode_SIze,char * Utf8)

{

int Unicode_Length;

if(Utf8 == NULL || Unicode == NULL )

return 0;

// UTF-8 轉 Unicode

Unicode_Length = MultiByteToWideChar(CP_UTF8, NULL, Utf8, strlen(Utf8), Unicode, Unicode_SIze);

Unicode[Unicode_Length] = NULL;

return Unicode_Length;

}

 

//——————————————————————

// UTF-8 轉 Unicode

//Utf8:UTF-8字符輸出

//Utf8_Size:UTF-8碼輸出緩衝區BYTE的長度

//Unicode:Unicode寬字符輸入

//返回值:Unicode所占字節數!

//——————————————————————

int Unicode_To_Utf8(char * Utf8,int Utf8_Size,WCHAR * Unicode)

{

int Utf8_Length;

if(Utf8 == NULL || Unicode == NULL)

return 0;

// UTF-8 轉 Unicode

Utf8_Length = WideCharToMultiByte(CP_UTF8, NULL, Unicode, wcslen(Unicode), Utf8, Utf8_Size, NULL, NULL);

Utf8[Utf8_Length] = NULL;

return Utf8_Length;

}

 

//—————————————————————————

//Ansi 轉 Utf8

//Utf8:UTF-8字符輸出

//Utf8_Size:UTF-8碼輸出緩衝區BYTE的長度

//Ansi:ANSI文本輸入

//Encode:ANSI文本字符編碼

//返回值:Utf8字節長度

//—————————————————————————

int Ansi_To_Utf8(char * Utf8,int Utf8_Size,char * Ansi,int Encode)

{

int Utf8_Length = NULL;

PWORD Unicode;

int   Unicode_Size;

int   Unicode_Length;

Unicode = (PWORD)Utf8;

Unicode_Size = Utf8_Size/2;

// Ansi 轉 Unicode

//Unicode_Length = Ansi_To_Unicode(Unicode,Unicode_Size,Ansi,Encode);

Unicode_Length = MultiByteToWideChar(Encode, NULL, Ansi,strlen(Ansi), Unicode, Unicode_Size);// 轉換

Unicode[Unicode_Length] = 0;

// Unicode 轉 Utf8

//Utf8_Length = ::Unicode_To_Utf8(Utf8,Utf8_Size,Unicode);

Utf8_Length = WideCharToMultiByte(CP_UTF8, NULL, Unicode, wcslen(Unicode), Utf8, Utf8_Size, NULL, NULL);

Utf8[Utf8_Length] = NULL;

return Utf8_Length;

}

//—————————————————————————

// Utf8 轉換 Ansi

// Ansi: ANSI文本輸出

// Ansi_Size:ANSI碼輸出緩衝區BYTE的長度

// Utf8: UTF-8字符輸入

// 返回值:Ansi字節長度

//—————————————————————————

int Utf8_To_Ansi(char * Ansi,int Ansi_Size,char * Utf8)

{

int Ansi_Length = NULL;

PWORD Unicode;

int   Unicode_Size;

int   Unicode_Length;

Unicode = (PWORD)Ansi;

Unicode_Size = Ansi_Size/2;

// Utf8 轉 Unicode

//Unicode_Length = Utf8_To_Unicode(Unicode,Unicode_Size,Utf8);

Unicode_Length = MultiByteToWideChar(CP_UTF8, NULL, Utf8, strlen(Utf8), Unicode, Unicode_Size);

Unicode[Unicode_Length] = NULL;

// Unicode 轉 Ansi

//Ansi_Length = ::Unicode_To_Ansi(Ansi,Ansi_Size,Unicode);

Ansi_Length = WideCharToMultiByte(CP_ACP, NULL, Unicode, wcslen(Unicode), Ansi, Ansi_Size, NULL, NULL);

Ansi[Ansi_Length] = NULL;

return Ansi_Length;

}

 

編碼類型 數值 說明
CP_ACP 0 默認ANSI代碼頁
CP_OEMCP 1 默認OEM代碼頁
CP_MACCP 2 默認MAC代碼頁
CP_THREAD_ACP 3 本線程ANSI代碼頁
CP_SYMBOL 42 SYMBOL轉換
CP_UTF7 65000 UTF-7轉換
CP_UTF8 65001 UTF-8轉換
CP_ANSI 1252 通用ANSI 代碼頁
ISO_8859_1 28591 西歐語言
ARABIC 1256 阿拉伯語
GENERAL 1252 通用
DUTCH 1252 荷蘭,德國
CZECH 1250 捷克斯洛伐克
HUNGARIAN 1250 匈牙利
ICELANDIC 1252 冰島
NORDIC 1252 北歐日耳曼民族的
NORWDAN 1252
POLISH 1250 波蘭
CYRILLIC 1251 西裏爾字母
SPANISH 1252 西班牙
SWEDFIN 1252
TURKISH 1254 土耳其語, 突厥語族
GREEK 1253 希臘
HEBREW 1255 希伯來語
JAPANESE 932 日本
KOREAN 949 朝鮮
BIG5 950 正體中文
GB2312 936 簡體中文
GBK 936 簡體中文
GB18030 54936 簡體中文
SLOVENIAN 1250 未開發

 

 

 

Windows之ANSI與UNICODE

Windows之ANSI與UNICODE

近日寫SEO應用程式,因現在目錄路徑可能會有中文字符或非ASCII字符,所以使用寬字符版的程式,但出現_T()與_TEXT()宏指令無定義:

error C2065: ‘_T’ : undeclared identifier

又不想直接使用L()宏指令定義寬自字符,百思不得其解.原來_T()與_TEXT()宏指令的定義在TCHAR.H文件,添加#include <TCHAR.h>即可解決.

VC使用#define _MBCS定義則使用ANSI字符,而定義#define _UNICODE 則使用UNICODE寬字符.如過想全局定義_MBCS或_UNICOD可在Settings設置如上圖.

Project Settings/C/C++/Category/General/Preprocessor definitions/ WIN32,_DEBUG,_WINDOWS,_UNICODE

鋼琴自學-加線音符和八度記號

鋼琴自學-加線音符和八度記號

加線音符(ledger line notes)是指在五線譜上或下加上短線的音符.

高八度記號用”8va”標記外加上一條標記範圍的直線,在高音譜號上表示彈奏音符的高八度,

低八度記號用”8vb”標記外加上一條標記範圍的直線,在低音譜號上表示彈奏音符的低八度.

十六度記號用”16va”標記外加上一條標記範圍的直線,在高音譜號上表示彈奏音符的高兩八度音,在低音譜號上表示彈奏音符的低兩八度音.

 

Overture是專業五線譜軟件,特記下”八度記號”加入步驟.

  1. 選擇工具
  2. 選擇音符
  3. 音符/組/八度記號
  4. 按確定

鋼琴自學-拍號

鋼琴自學-拍號

拍號由上下兩數組成,在五線譜調號後面,上面的數字表示一小節含幾拍,下面的數字表示音值比率

 

上面的數字表示一小節含幾拍

4/4表示一個小節後四拍,該小節所有音符加來是四拍, 4/4因為用得多所以使用大寫C表示.

3/4表示一個小節後三拍,該小節所有音符加來是三拍

 

下面的數字表示音符的音值比率

4是最常見音值比率,意即四分音符為一單位拍,按照這個比值算如下表

音符
八分音符 1/2拍
四分音符 一拍
二分音符 二拍
符點二分音符 三拍
全音符 四拍

 

8意即八分音符為一單位拍,如下表

音符
八分音符 一拍
四分音符 二拍
二分音符 四拍
符點二分音符 六拍
全音符 八拍

 

示例如上圖

3/4表示每一小節3拍,四分音符為一單位拍,第一小節3個C每個一拍,第二小節二分音符C兩拍,加上四分音符C一拍,一共三拍.

鋼琴自學-調號

鋼琴自學-調號

調號是指寫在指寫在五線譜譜號後面的變音記號,包括升號和降號.

調號在五線譜的高音譜號和低音譜號的後面,調號標明該作品所使用的調.調號是作品的一部分,它將傳遞給你作品的重要信息,通過調號你可以瞭解整段作品的的遊戲規則,直到在調號變化之前.

如果調號的標記是FL,那麼所有的F都有升半音,直到F”的出現

如果調號的標記是Bb和E:,那麼所有的B和E都要降半音,直到B”和E”的出現

如果在五線譜的開端無看到升號或降號,那並不是說作品就沒有調,而是表明作品是C調沒有升音或降音.

平板電腦-安裝Windows10

平板電腦-安裝Windows10

我果台雜牌平板更換電池後獲得新的生命.平板本為雙系統Win8+Android.因為硬盤只有64GB再分給兩系統使用可利用率實在太低.故想重新分區安裝Win10.在微軟下載Windows10 ISO官方鏡像.版本號為1709居然無法安裝第三應用,只可以安裝在應用商店下載的應用或者購買專業版…暈!也就想激活Win10都無可能.之後安裝早期的Win10-ISO鏡像才成攻激活.

鋼琴自學-升號和降號與還原記號

鋼琴自學-升號和降號
鋼琴自學-還原記號

黑鍵是根據相鄰白鍵所發音來命名,在白鍵的音名上加”升號”或”降號”

 

升號(sharp)

五線譜音符左側”#”稱為”升號”,它表示把音符的音級升高一個變化音級

不論彈奏高音譜表(右手)或低音譜表(左手),音符前的升號都對應該音符所示白鍵右側的黑鍵

沒有B#因為B和C之間沒有黑鍵

沒有E#因為E和F之間沒有黑鍵

 

降號(flat)

五線譜音符左側”b”稱為”降號”,它表示把音符的音級降低一個變化音級

不論彈奏高音譜表(右手)或低音譜表(左手),音符前的降號都對應該音符所示白鍵左側的黑鍵

沒有Cb因為B和C之間沒有黑鍵

沒有Fb因為E和F之間沒有黑鍵

 

還原記號(natural sign)

還原記號(“),即取消升號或降號,從升音或降音之後的黑鍵回到初始的白鍵,

在音符前標記的升號與降號,對本小節同音高的音起作用,直到出現還原記號,而到下一個小節又恢復原先的調號

 

 

 

Word輸入音符

Word輸入音符

在撰寫與音樂相關的文章時會大量用到五線譜音符,但系統自帶的字體一般都不帶五線譜音符.幸好有專用的五線譜字體

  1. 下載akvo.ttf五線譜字體
  2. 解壓後把ttf字體文件存放到系統的Fonts字體文件夾,以WinXP為例路徑為”C:\WINDOWS\Fonts”
  3. 打開WORD
  4. 字體選擇akvo字體
  5. 輸入鍵對應的音符、休止符、譜號查下表
  6. 按Shift可以改變音符的符幹方向
音符、休止符、譜號對應的輸入鍵

鋼琴自學-音符時值

鋼琴自學-音符時值
鋼琴自學-音符時值

全音符(whole note)

全音符只有空心符頭沒有符幹(符頭延伸的直線).一個全音符時值為四拍,即按下琴鍵並保持四拍,上圖彈E並保持四拍.

 

二分音符(half note)

全音符由空心符頭和符幹組成.一個二分音符時值為兩拍,即按下琴鍵並保持兩拍,上圖彈兩個G每個兩拍

 

四分音符(quarter note)

四分音符由實心符頭和符幹組成.一個四分音符時值為一拍,即按下琴鍵並保持一拍,上圖彈四個F每個保持一拍

 

八分音符(eighth note)

八分音符由實心符頭于符幹和符尾組成,符尾為符幹旁側伸出的一條彎曲,一個八分音符時值為1/2,當兩個或以上的八分音符挨在一起時在它們上面加一條橫線進行標記, 上圖彈七個E每個保持1/2

 

符點二分音符(dotted half note)

音符後有一個點表示增加該音符時值1/2.符點二分音符時值為三拍,二分音符為兩拍加符點表示加1/2拍既三拍.

 

休止符(tacet)

休止符用於表示停頓的時間長短

 

全休止符(whole tacet)

全休止符表示停頓四拍

 

二分休止符(half tacet)

二分休止符表示停頓兩拍

 

四分休止符(quarter tacet)

四分休止符表示停頓一拍

 

八分休止符(eighth tacet)

八分休止符表示停頓1/2

 

音符

時值

符標

全音符

四拍

A

二分音符

兩拍

B

四分音符

一拍

C

八分音符

1/2

D

符點二分音符

三拍

H

 

 

休止符

停頓時長

符標

全休止符

四拍

U

二分休止符

兩拍

V

四分休止符

一拍

W

八分休止符

1/2

X

 

鋼琴自學-音符與琴鍵對號入座

鋼琴自學-音符與琴鍵對號入座

鋼琴自學-音符與琴鍵對號入座

右手部分

”高音譜號”的五條線對應五個音符,分別是E、G、B、D和F

”高音譜號”的四個間對應四個音符,分別是F、A、C和E.你可以記為FACE

 

右手部分

”低音譜號”的五條線對應五個音符,分別是G、B、D、F和A

”低音譜號”的四個間對應四個音符,分別是A、C、E和G

Word輸入頓號

Word輸入頓號

漢字本來是無標點符號是進代先引入.所以頓號是漢字標點符號,要在Word或其它文本中輸入頓號”、”

  1. 按Ctrl+Shift切換為中文輸入法
  2. 按Ctrl+Period(句號鍵)切換為中文標點
  3. 按“|”鍵則可輸入頓號”、”

 

總結左下輸入法快捷鍵如下

  1. 按Ctrl+Shift切換輸入法
  2. 按Shift+Space(空格鍵)全角與半角切換
  3. 按Ctrl+Space(空格鍵)輸入法與非輸入法之間切換
  4. 按Ctrl+Period(句號鍵)中英文標點切換

 

 

鋼琴自學-五線譜的構成

鋼琴自學-五線譜的構成

鋼琴五線譜由兩組五線譜組成,把兩組五線譜用花括號連接起來構成大譜表.上方一組用右手彈奏,下方一組用左手彈奏.每組五線譜都包括了五條平行橫”線”和四個”間”.線和間用於記錄鋼琴音符.

 

高音譜號(treble clef)~

上方五線譜最左邊的記號”~”是”高音譜號”,用於指示它後面的音符用右手彈奏.它另有“G譜號”之稱.”高音譜號”的中段要畫在五線譜的第二線開始捲曲標記,這條線用於記錄音符G.

 

低音譜號(bass clef)`

下方五線譜最左邊的記號”`”是”低音譜號”,用於指示它後面的音符用左手彈奏.它另有“F譜號”之稱. ”低音譜號”的兩個圓點要畫在五線譜的第二線的上下兩個”間”,這條線用於記錄音符F.

 

小節(measure)和小節線(bar line)

“小節”是指小節線之間的部分,小節線把各小節隔開,不同節可以採用不同的拍子

平板電腦-無鍵盤進入Bios

平板電腦-無鍵盤進入Bios

要進入平板的Bios只需在開機時按ESC鍵即可,但如過你身邊無平板鍵盤,也可以通過軟鍵盤進入Bios

  1. 開機點擊屏幕中下側邊,彈出軟鍵盤.要點觸多幾下.
  2. ESC在F1下面,即第二行第一個
  3. 默認只有兩秒,一定要快
  4. 進入Bios後可設置提示超時,Boot/Setup Prompt Timeout.修該為5至8秒放便按軟鍵盤
  5. 保存設置並重啟Save & Exit/Save Changes and Reset

 

平板電腦-更換鋰電池

平板電腦-更換鋰電池

本人在多年買的一台雜牌平板電腦,因電池衰老已無法開機,其實新機也是一到兩個小時,一直閒置在家.近日在網上買得兼容電池,原裝的鋰電池是3.8V(伏)8000mAh(毫安),但兼容電池是3.7V(伏)12000mAh(毫安).由兩塊6000mah鋰電池並聯而成.紅白黑三線鋰電池,紅線為電池正極,黑線為電池負極,白線為溫控檢測端,當鋰電池放電時產生化學反應鋰電池溫度會升高,溫控熱敏電阻輸出信號給電池保護電路,讓電池停止放電起保護作用.但安裝去後只能充到95%就充不入.不過台平板可以重新運作OK.

鋼琴自學-坐姿與手形

鋼琴自學-坐姿與手形

鋼琴彈奏時正確的座姿與手形可使你身題保持放鬆,避免勞累與酸疼

距離:

移動琴凳尋找身體與鋼琴的最佳距離

 

坐姿:

量好的坐姿是兩肩自然下垂並略略向後拉伸,面向鍵盤正中而坐,雙腳平穩的接觸地面,與踏板對齊偏於踩踏.膝蓋在鍵盤下放,手肘與鍵盤基盤平行.

 

駝背:

琴凳距離鍵盤過遠

 

聳肩:

琴凳過矮造成琴鍵過高引起,並會引起頸背肌肉酸痛

 

手形

正確的手形是把雙手放在琴鍵上,收心供起,手指放鬆用指肚觸鍵,如過手指塌掉會影響彈奏速度.

鋼琴自學-拇指穿過與三指越過

鋼琴自學-拇指穿過與三指越過

按下表練習三指越過,把右手大拇指放在中央C上,HC表示“高八度C”,注意指法特別是拇指穿過三指.

標記 1 2 3 1 2 3 4 5
音符 C D E F G A B HC
唱名 Do Re Mi Fa Sol La Si Do

把右手小指放在高八度C下行至中央C

標記 5 4 3 2 1 3 2 1
音符 HC B A G F E D C
唱名 Do Si La Sol Fa Mi Re Do

按下表練習拇指穿過,右手大拇指放在中央C張開手掌用小指觸及高八度C,左右彈奏這兩個音感受跨八個音時手掌的伸展,HC表示“高八度C”

標記 1 5 1 5 1 5 1 5
音符 C HC C HC C HC C HC
唱名 Do Do Do Do Do Do Do Do

 

按下表練習左手三指越過,把左手大拇指放在中央C上,LC表示“底八度C”,注意指法特別是大拇指穿越三指.

標記 1 2 3 1 2 3 4 5
音符 C B A G F E D LC
唱名 Do Si La Sol Fa Mi Re Do

把左手小指放在底八度C上行至中央C

標記 5 4 3 4 5 3 4 5
音符 LC D E F G A B C
唱名 Do Re Mi Fa Sol La Si Do
唱名 Do Si La Sol Fa Mi Re Do

練習左手拇指穿過,左手放在中央C張開手掌用小指觸及低八度C,左右彈奏這兩個音感受跨八個音時手掌的伸展,LC表示“低八度C”

標記 1 5 1 5 1 5 1 5
音符 C LC C LC C LC C LC
唱名 Do Do Do Do Do Do Do Do

 

標記請閱讀手指位置

鋼琴自學-手指位置

鋼琴自學-手指位置右手
鋼琴自學-手指位置左手

琴建手指位置的擺放如下表,彈奏時說出各指對應的唱名

 

右手

音符 C D E F G
標記 1 2 3 4 5
手指 大拇指 食指 中指 無名指 小指
唱名 Do Re Mi Fa Sol

 

左手

音符 C B A G F
標記 1 2 3 4 5
手指 大拇指 食指 中指 無名指 小指
唱名 Do Si La Sol Fa