像素着色器

电脑应用

像素着色器是一种小程序,用于对渲染过程中的每个像素进行编程着色,提供了比固定功能流水线更高的灵活性和控制力。

应用
本示例把一张纹理贴图应用于一个四边形。本例和前例的区别在于:
顶点数据结构和FVF码包含了纹理坐标。顶点数据包含了u, v数据。因为像素的颜色将从纹理贴图得到,所以顶点数据不再需要漫反射色。 用IDirect3DDevice9::SetTexture把纹理连接到纹理层0。 着色器用t0纹理寄存器取代v0漫反射色寄存器。 示例代码如下:
// 定义顶点数据结构。
struct CUSTOMVERTEX
{
FLOAT x, y, z;
FLOAT u1, v1;
};
// 定义相应的FVF码。
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_TEX|D3DFVF_TEXCOORDSIZE2(0))
// 创建包含位置和纹理坐标的顶点数据。
static CUSTOMVERTEX g_Vertices[]=
{
// x y z u1 v1
{ -1.0f, -1.0f, 0.0f, 0, 1, },
{ 1.0f, -1.0f, 0.0f, 1, 1, },
{ 1.0f, 1.0f, 0.0f, 1, 0, },
{ -1.0f, 1.0f, 0.0f, 0, 0, },
// 为了和Windows从上到下的约定一致,v1被颠倒了。
// 左上角的纹理坐标为(0,0)。
// 右下角的纹理坐标为(1,1)。
};
// 创建纹理。这个文件包含在供下载的DirectX 9.0 SDK的媒体文件中。
TCHAR strTexturePath[512];
DXUtil_FindMediaFileCb( strTexturePath, sizeof(strTexturePath),
LPDIRECT3DTEXTURE9 m_pTexture0;
D3DUtil_CreateTexture( m_pd3dDevice, strTexturePath,
&m_pTexture0, D3DFMT_R5G6B5 );
// Create the pixel shader.
TCHAR strShaderPath[512];
DXUtil_FindMediaFileCb( strShaderPath, sizeof(strShaderPath),
这个函数是示例框架使用的一个辅助函数,许多示例都以它为基础。
LPD3DXBUFFER pCode; // 用来存放经过汇编的着色器代码的缓存
LPD3DXBUFFER pErrorMsgs; // 用来存放错误信息的缓存
LPDIRECT3DPIXELSHADER9 m_pPixelShader;
D3DXAssembleShaderFromFile( strShaderPath, 0, NULL, &pCode, NULL );
m_pd3dDevice->CreatePixelShader( (DWORD*)pCode->GetBufferPointer(),
&m_pPixelShader );
m_pd3dDevice->SetPixelShader( m_pPixelShader );
// 载入纹理并渲染输出像素。
m_pd3dDevice->SetTexture( 0, m_pTexture0 );
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
// 把纹理贴图应用于物体的顶点。
ps_1_1 // 文件的第一条必须是版本指令。
tex t0 // 声明纹理寄存器t0,从纹理层0载入。
mov r0, t0 // 把纹理寄存器数据(t0)复制到输出寄存器(r0)。
得到的图像如下面所示。
来源
在Microsoft DirectX 8.0之前,Microsoft Direct3D 使用固定功能流水线把三维几何体转换为屏幕上的像素。用户通过设置流水线的属性来控制Direct3D进行变换、光照和渲染像素的方式。固定功能顶点格式在编译的时候定义并决定输入顶点的格式,一旦定义,用户在运行的时候就几乎无法控制流水线的改变。
通过允许对顶点的变换、光照和对每个像素的着色等功能进行编程,着色器把图形流水线引入了一个新的高度。像素着色器是一些小程序,在对三角形进行光栅化操作时运行。这在渲染像素的方法上给了用户更高一级的灵活性。
软件原理
纹理寻址指令提供了多种读取和应用纹理数据的操作。着色器具有这样的功能,可以给颜色分量设置掩码以及交换颜色分量。着色器的正文看起来有点像汇编语言,它用Direct3D扩展(D3DX)进行汇编,输入可以是文本字符串或是文件。汇编器的输出是一系列操作码,应用程序可以通过IDirect3DDevice9::CreatePixelShader方法把这些操作码提供给Direct3D。
本示例用像素着色器对一个四边形的漫反射色进行高洛德插值。示例显示了着色器文件的内容以及应用程序中所需的代码。
创建步骤
第1步:检查对像素着色器的支持。 第2步:声明顶点数据。 第3步:设计像素着色器。 第4步:创建像素着色器。第5步:渲染输出像素。 如果读者已经知道如何构建并运行Direct3D示例,那么可以从本示例中复制代码并粘贴到已有的应用程序中。
步骤一
要检查对像素着色器的支持,应该使用以下代码。这个例子检查1.1版本的像素着色器。
D3DCAPS9 caps;
m_pd3dDevice->GetDeviceCaps(&caps); // 使用m_pd3dDevice前要进行初始化
if( caps.PixelShaderVersion < D3DPS_VERSION(1,1) )
return E_FAIL;
caps结构会返回硬件可用的能力。要用D3DPS_VERSION宏检查当前硬件支持的所有着色器版本。如果caps返回的版本小于1.1,那么这个调用会失败。反之,对所有大于或等于1.1的版本,调用会成功。如果硬件不支持被测试的着色器版本,那么应用程序将不得不退而使用别的渲染方法(也许可以使用一个较低版本的着色器)。
步骤二
这个示例使用了一个四边形,由两个三角形组成。每个顶点的数据结构包含了位置和漫反射色数据。D3DFVF_CUSTOMVERTEX宏定义了与顶点数据相匹配的数据结构。实际的顶点数据在全局数组g_Vertices中声明。四个顶点以原点为中心,每个顶点具有不同的漫反射色。
// 声明顶点数据结构。
struct CUSTOMVERTEX
{
FLOAT x, y, z;
DWORD diffuseColor;
};
// 声明自定义FVF宏。
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
// 声明顶点位置和漫反射色数据。
CUSTOMVERTEX g_Vertices[]=
{
// x y z 漫反射色
{ -1.0f, -1.0f, 0.0f, 0xffff0000 }, // 红 – 左下
{ +1.0f, -1.0f, 0.0f, 0xff00ff00 }, // 绿 – 右下
{ +1.0f, +1.0f, 0.0f, 0xff0000ff }, // 蓝 – 右上
{ -1.0f, +1.0f, 0.0f, 0xffffffff }, // 白 – 左上
};
步骤三
这个着色器把经过高洛德插值的漫反射色数据复制到输出像素。着色器文件PixelShader.txt如下所示:
ps_1_1 // 版本指令
mov r0,v0 // 把顶点的漫反射色复制到输出寄存器。
像素着色器文件的第一条指令声明了像素着色器的版本,此处为1.1。
第二条指令把颜色寄存器(v0)的内容复制到输出寄存器(r0)。因为在第1步中声明的顶点数据已经包含了经过插值的漫反射色,所以颜色寄存器包含了顶点的漫反射色。输出寄存器决定渲染目标使用的像素颜色(因为本例中没有更多的处理,如雾,所以输出寄存器就是最终的像素颜色)。
步骤四
像素着色器由像素着色器指令创建。本例中,指令被包含在一个单独的文件中。指令也可以被包含在一个文本字符串中。
LPD3DXBUFFER pCode; // 存放经过汇编的着色器代码的缓存
LPD3DXBUFFER pErrorMsgs; // 存放错误信息的缓存
TCHAR strPixelShaderPath[512];// 用来定位着色器文件
DXUtil_FindMediaFileCb( strPixelShaderPath, sizeof(strPixelShaderPath),
这个函数是示例框架使用的一个辅助函数,许多示例都以它为基础。
LPDIRECT3DPIXELSHADER9 m_pPixelShader;
D3DXAssembleShaderFromFile( strPixelShaderPath, NULL, NULL, 0,
&pCode, &pErrorMsgs, NULL );
m_pd3dDevice->CreatePixelShader( (DWORD*)pCode->GetBufferPointer(),
&m_pPixelShader );
着色器创建完成后,指针m_pPixelShader用来对它进行引用。
步骤五
除了用像素着色器句柄来设置着色器外,渲染输出像素的过程和使用固定功能流水线类似。
// 在本例中关闭光照。它不会对最终像素的颜色产生影响。
// 像素颜色完全由经过插值的顶点颜色决定。
m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
m_pd3dDevice->SetStreamSource( 0, m_pQuadVB, sizeof(CUSTOMVERTEX) );
m_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
m_pd3dDevice->SetPixelShader( m_pPixelShader );
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
源顶点数据由SetStreamSource设置。本例中,SetFVF使用在声明顶点数据时定义的FVF码告诉Direct3D进行固定功能顶点处理。顶点着色器和像素着色器既可以一起使用,也可以分开使用。可以用固定功能流水线代替这两者。SetPixelShader设置像素着色器,而DrawPrimitive则绘制四边形。
确认对像素着色器的支持
应用程序可以查询D3DCAPS9的成员以确定硬件对像素着色器所涉及的操作的支持程度。下表列出了与可编程像素处理有关的设备能力。
可用于像素着色器的纹理取样器的数量取决于像素着色器的版本。
PixelShaderVersion的第一个字节包含次版本号,第二个字节包含主版本号。经过汇编的着色器的第一个标记就是像素着色器的版本。每种硬件实现都会设置该版本号,表示它能完全支持的像素着色器的最高版本。
纹理操作的转换
像素着色器在以下几个方面扩展并一般化了Microsoft DirectX® 6.0和7.0的多重纹理能力。
加入了一组通用读/写寄存器,这样就允许更为灵活的表达式。用D3DTA_CURRENT的连续级联需要为每层指定一个单独的结果寄存器参数。 D3DTOP_MODULATE2X和D3DTOP_MODULATE4X纹理操作被分成了单独的修饰符,可用于任何指令。这样就无需单独的D3DTOP_MODULATE和D3DTOP_MODULATE2X操作了。 乘加操作加入了可选的第三个参数,因此程序化的像素着色器可以执行arg1 ×arg2 + arg0的操作。这样就不再需要D3DTOP_MODULATEALPHA_ADDCOLOR和D3DTOP_MODULATECOLOR_ADDALPHA 纹理操作了。 混合操作加入了可选的第三个参数,因此程序化的像素着色器可以用arg0作为arg1和arg2之间的混合比。这样就不再需要D3DTOP_BLENDDIFFUSEALPHA, D3DTOP_BLENDTEXTUREALPHA, D3DTOP_BLENDFACTORALPHA, D3DTOP_BLENDTEXTUREALPHAPM, 和D3DTOP_BLENDCURRENTALPHA纹理操作了。 对纹理寻址的修改操作,如D3DTOP_BUMPENVMAP,被从颜色和阿尔法操作中分离出来并作为第三种操作类型,专门用于纹理寻址操作。 为了有效地支持这种新增的灵活性,API的语法从DWORD对改成了ASCII汇编代码语法。这样就暴露了程序化的像素着色器所提供的功能。
注意在使用像素着色器时,镜面反射加法不专门由一个渲染状态控制,如果需要,这可能由像素着色器实现。但是,雾混合仍然由固定功能流水线执行。
对纹理的一些考虑
像素着色器完全取代了由Microsoft DirectX® 6.0和7.0的多重纹理API提供的像素混合功能,尤其是那些由D3DTSS_COLOROP, D3DTSS_COLORARG1, D3DTSS_COLORARG2, D3DTSS_ALPHAOP, D3DTSS_ALPHAARG1和D3DTSS_ALPHAARG2纹理层状态、相关的参数和修饰符定义的操作。如果设置了程序化的像素着色器,那么这些状态会被忽略。
取样状态
如果像素着色器正在运行,那么以下纹理层状态仍然会被使用。对这些状态的使用取决于像素着色器的版本,如下表所示。
如果像素着色器正在运行,那么下面的取样器状态仍然会被使用。
因为纹理层状态不是像素着色器的一部分,在编译着色器时它们是不可用的,所以驱动程序无法对它们做任何假定。例如,驱动程序不能在那时区分出双线性过滤和三线性过滤。应用程序可以自由地改变这些状态而无需重新生成当前绑定的着色器。
纹理取样
纹理取样和过滤操作由标准纹理层状态中的放大、缩小、mip过滤、以及环绕寻址模式控制。更多信息,请参阅纹理层状态。因为驱动程序在编译时也无法得到这些信息,所以着色器必须能够在这些状态改变后继续运行。应用程序负责设置像素着色器所需的正确类型的纹理(二维贴图,立方体贴图,立体贴图等)。如果设置不正确的纹理类型,那么将会产生不可预料的结果。
处理
其它一些像素操作——如雾混合、模板操作、以及渲染目标混合——在着色器执行以后发生。为了支持本主题描述的新特性,渲染目标混合的语法已经做了更新。
输入
对像素着色器版本1.1到2.0来说,漫反射色和镜面反射色在给着色器使用之前被截取到范围0到1之间,因为这是着色器的有效输入范围。
输入到像素着色器的颜色值被认为是经过透视校正的,但并非所有硬件都能保证这一点。寻址处理器根据纹理坐标产生的颜色总是以透视校正的方式进行迭代。但是,在迭代过程中,它们也会被截取到范围0到1之间。
输出
对像素着色器版本1.1到1.4来说,像素着色器产生的输出是寄存器r0的内容。该寄存器的值会在着色器处理结束后被送往雾处理阶段和渲染目标混合器。
对像素着色器版本2.0以上来说,输出的颜色值为oC0到oC4。
像素着色器示例
本节包含三个像素着色器示例。每个示例都建立在前一个示例的基础上,并增加一些功能。
应用纹理贴图 把顶点漫反射色和纹理进行混合 用颜色值把两张纹理进行混合
混合
本例把纹理贴图中的颜色与顶点的颜色进行混合。本例与前例的区别如下:
顶点的数据结构,FVF码和顶点数据包含了漫反射色。 着色器文件用乘法(mul)指令把纹理的颜色和顶点的漫反射色进行混合。 创建纹理和载入纹理的代码是相同的,放在这里是为了保持代码的完整性。
struct CUSTOMVERTEX
{
FLOAT x, y, z;
DWORD color1;
FLOAT tu1, tv1;
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1|
D3DFVF_TEXCOORDSIZE2(0))
static CUSTOMVERTEX g_Vertices[]=
{
// x y z diffuse u1 v1
{ -1.0f, -1.0f, 0.0f, 0xffff0000, 0, 1, }, // 红
{ 1.0f, -1.0f, 0.0f, 0xff00ff00, 1, 1, }, // 绿
{ 1.0f, 1.0f, 0.0f, 0xff0000ff, 1, 0, }, // 蓝
{ -1.0f, 1.0f, 0.0f, 0xffffffff, 0, 0, }, // 白
// 为了和Windows从上到下的约定一致,v1被颠倒了。
// 左上角的纹理坐标为(0,0)。
// 右下角的纹理坐标为(1,1)。
};
// 创建纹理。这个文件包含在供下载的DirectX 9.0 SDK的媒体文件中。
TCHAR strTexturePath[512];
DXUtil_FindMediaFileCb( strTexturePath, sizeof(strTexturePath),
LPDIRECT3DTEXTURE9 m_pTexture0;
D3DUtil_CreateTexture( m_pd3dDevice, strTexturePath,
&m_pTexture0, D3DFMT_R5G6B5 );
// 创建像素着色器。
TCHAR strShaderPath[512];
DXUtil_FindMediaFileCb( strShaderPath, sizeof(strShaderPath),
LPD3DXBUFFER pCode; // 用来存放经过汇编的着色器代码的缓存
LPD3DXBUFFER pErrorMsgs; // 用来存放错误信息的缓存
LPDIRECT3DPIXELSHADER9 m_pPixelShader;
D3DXAssembleShaderFromFile( strShaderPath, 0, NULL, &pCode, NULL );
m_pd3dDevice->CreatePixelShader( (DWORD*)pCode->GetBufferPointer(),
&m_pPixelShader );
m_pd3dDevice->SetPixelShader( m_pPixelShader );
// 载入纹理并渲染输出像素。
m_pd3dDevice->SetTexture( 0, m_pTexture0 );
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
ps_1_1 // 版本指令
tex t0 // 声明纹理寄存器t0, 从纹理层0载入
mul r0, v0, t0 // v0*t0, 然后复制到r0
着色器的输入如下面所示。第一幅图为顶点颜色,第二幅图为纹理贴图
得到的图像如下面所示,也就是顶点的颜色和纹理贴图混合的结果。
纹理进行混合
本例把两张纹理贴图进行混合,顶点的颜色用来决定每张纹理贴图的颜色所占的比例。本例和前例的区别如下:
因为使用了两张纹理,所以顶点的数据结构,FVF码,以及顶点数据包含了第二组纹理坐标。另外IDirect3DDevice9::SetTexture也调用了两次,并设置两个纹理层的状态。 着色器文件声明了两个纹理寄存器并使用线性插值(lrp)指令把两张纹理进行混合。漫反射色的值用来决定两张纹理在输出的颜色中所占的比例。 下面是示例代码。
struct CUSTOMVERTEX
{
FLOAT x, y, z;
DWORD color;
FLOAT tu1, tv1;
FLOAT tu2, tv2; // 第二组纹理坐标
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3D_FVF_DIFFUSE|D3DFVF_TEX2|
D3DFVF_TEXCOORDSIZE4(0))
static CUSTOMVERTEX g_Vertices[]=
{
// x y z color u1 v1 u2 v2
{ -1.0f, -1.0f, 0.0f, 0xff0000ff, 1.0f, 1.0f, 1.0f, 1.0f },
{ +1.0f, -1.0f, 0.0f, 0xffff0000, 0.0f, 1.0f, 0.0f, 1.0f },
{ +1.0f, +1.0f, 0.0f, 0xffffff00, 0.0f, 0.0f, 0.0f, 0.0f },
{ -1.0f, +1.0f, 0.0f, 0xffffffff, 1.0f, 0.0f, 1.0f, 0.0f },
};
// 创建纹理。这个文件包含在供下载的DirectX 9.0 SDK的媒体文件中。
TCHAR strTexturePath[512];
LPDIRECT3DTEXTURE9 m_pTexture0, m_pTexture1;
DXUtil_FindMediaFileCb( strTexturePath, sizeof(strTexturePath),
D3DUtil_CreateTexture( m_pd3dDevice, strTexturePath,
&m_pTexture0, D3DFMT_R5G6B5 );
DXUtil_FindMediaFileCb( strTexturePath, sizeof(strTexturePath),
D3DUtil_CreateTexture( m_pd3dDevice, strTexturePath,
&m_pTexture0, D3DFMT_R5G6B5 );
// 创建像素着色器。
TCHAR strShaderPath[512];
DXUtil_FindMediaFileCb( strShaderPath, sizeof(strShaderPath),
LPD3DXBUFFER pCode; // 用来存放经过汇编的着色器代码的缓存
LPD3DXBUFFER pErrorMsgs; // 用来存放错误信息的缓存
LPDIRECT3DPIXELSHADER9 m_pPixelShader;
D3DXAssembleShaderFromFile( strShaderPath, 0, NULL, &pCode, NULL );
m_pd3dDevice->CreatePixelShader( (DWORD*)pCode->GetBufferPointer(),
&m_pPixelShader );
m_pd3dDevice->SetPixelShader( m_pPixelShader );
// Load the textures stages.
m_pd3dDevice->SetTexture( 0, m_pTexture0 );
m_pd3dDevice->SetTexture( 1, m_pTexture1 ); // 使用第二层纹理
m_pd3dDevice->SetStreamSource( 0, m_pQuadVB, sizeof(CUSTOMVERTEX) );
m_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
m_pd3dDevice->SetPixelShader( m_pPixelShader );
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
ps_1_1 // 像素着色器版本。
tex t0 // 纹理寄存器t0从第0层载入。
tex t1 // 纹理寄存器t1从第1层载入。
mov r1, t1 // 把纹理t1复制到输出寄存器r1。
lrp r0, v0, t0, r1 // 用v0中指定的比例在t0和r1间进行线性插值。
得到的图像如下:
调试
调试
Microsoft Visual Studio 存在一个扩展以支持对某些类型的顶点着色器进行调试。更多信息请参阅着色器调试器。
另一个示例程序MFC Tex Sample是SDK安装的组成部分。这个MFC程序是学习如何在固定功能流水线中进行多重纹理混合操作的一个不错的方法。
全国各地天气预报查询

上海市

  • 市辖区
  • 云南省

  • 临沧市
  • 云南省

  • 丽江市
  • 云南省

  • 保山市
  • 云南省

  • 大理白族自治州
  • 云南省

  • 德宏傣族景颇族自治州
  • 云南省

  • 怒江傈僳族自治州
  • 云南省

  • 文山壮族苗族自治州
  • 云南省

  • 昆明市
  • 云南省

  • 昭通市
  • 云南省

  • 普洱市
  • 云南省

  • 曲靖市
  • 云南省

  • 楚雄彝族自治州
  • 云南省

  • 玉溪市
  • 云南省

  • 红河哈尼族彝族自治州
  • 云南省

  • 西双版纳傣族自治州
  • 云南省

  • 迪庆藏族自治州
  • 内蒙古自治区

  • 乌兰察布市
  • 内蒙古自治区

  • 乌海市
  • 内蒙古自治区

  • 兴安盟
  • 内蒙古自治区

  • 包头市
  • 内蒙古自治区

  • 呼伦贝尔市
  • 内蒙古自治区

  • 呼和浩特市
  • 内蒙古自治区

  • 巴彦淖尔市
  • 内蒙古自治区

  • 赤峰市
  • 内蒙古自治区

  • 通辽市
  • 内蒙古自治区

  • 鄂尔多斯市
  • 内蒙古自治区

  • 锡林郭勒盟
  • 内蒙古自治区

  • 阿拉善盟
  • 北京市

  • 市辖区
  • 吉林省

  • 吉林市
  • 吉林省

  • 四平市
  • 吉林省

  • 延边朝鲜族自治州
  • 吉林省

  • 松原市
  • 吉林省

  • 白城市
  • 吉林省

  • 白山市
  • 吉林省

  • 辽源市
  • 吉林省

  • 通化市
  • 吉林省

  • 长春市
  • 四川省

  • 乐山市
  • 四川省

  • 内江市
  • 四川省

  • 凉山彝族自治州
  • 四川省

  • 南充市
  • 四川省

  • 宜宾市
  • 四川省

  • 巴中市
  • 四川省

  • 广元市
  • 四川省

  • 广安市
  • 四川省

  • 德阳市
  • 四川省

  • 成都市
  • 四川省

  • 攀枝花市
  • 四川省

  • 泸州市
  • 四川省

  • 甘孜藏族自治州
  • 四川省

  • 眉山市
  • 四川省

  • 绵阳市
  • 四川省

  • 自贡市
  • 四川省

  • 资阳市
  • 四川省

  • 达州市
  • 四川省

  • 遂宁市
  • 四川省

  • 阿坝藏族羌族自治州
  • 四川省

  • 雅安市
  • 天津市

  • 市辖区
  • 宁夏回族自治区

  • 中卫市
  • 宁夏回族自治区

  • 吴忠市
  • 宁夏回族自治区

  • 固原市
  • 宁夏回族自治区

  • 石嘴山市
  • 宁夏回族自治区

  • 银川市
  • 安徽省

  • 亳州市
  • 安徽省

  • 六安市
  • 安徽省

  • 合肥市
  • 安徽省

  • 安庆市
  • 安徽省

  • 宣城市
  • 安徽省

  • 宿州市
  • 安徽省

  • 池州市
  • 安徽省

  • 淮北市
  • 安徽省

  • 淮南市
  • 安徽省

  • 滁州市
  • 安徽省

  • 芜湖市
  • 安徽省

  • 蚌埠市
  • 安徽省

  • 铜陵市
  • 安徽省

  • 阜阳市
  • 安徽省

  • 马鞍山市
  • 安徽省

  • 黄山市
  • 山东省

  • 东营市
  • 山东省

  • 临沂市
  • 山东省

  • 威海市
  • 山东省

  • 德州市
  • 山东省

  • 日照市
  • 山东省

  • 枣庄市
  • 山东省

  • 泰安市
  • 山东省

  • 济南市
  • 山东省

  • 济宁市
  • 山东省

  • 淄博市
  • 山东省

  • 滨州市
  • 山东省

  • 潍坊市
  • 山东省

  • 烟台市
  • 山东省

  • 聊城市
  • 山东省

  • 菏泽市
  • 山东省

  • 青岛市
  • 山西省

  • 临汾市
  • 山西省

  • 吕梁市
  • 山西省

  • 大同市
  • 山西省

  • 太原市
  • 山西省

  • 忻州市
  • 山西省

  • 晋中市
  • 山西省

  • 晋城市
  • 山西省

  • 朔州市
  • 山西省

  • 运城市
  • 山西省

  • 长治市
  • 山西省

  • 阳泉市
  • 广东省

  • 东莞市
  • 广东省

  • 中山市
  • 广东省

  • 云浮市
  • 广东省

  • 佛山市
  • 广东省

  • 广州市
  • 广东省

  • 惠州市
  • 广东省

  • 揭阳市
  • 广东省

  • 梅州市
  • 广东省

  • 汕头市
  • 广东省

  • 汕尾市
  • 广东省

  • 江门市
  • 广东省

  • 河源市
  • 广东省

  • 深圳市
  • 广东省

  • 清远市
  • 广东省

  • 湛江市
  • 广东省

  • 潮州市
  • 广东省

  • 珠海市
  • 广东省

  • 肇庆市
  • 广东省

  • 茂名市
  • 广东省

  • 阳江市
  • 广东省

  • 韶关市
  • 广西壮族自治区

  • 北海市
  • 广西壮族自治区

  • 南宁市
  • 广西壮族自治区

  • 崇左市
  • 广西壮族自治区

  • 来宾市
  • 广西壮族自治区

  • 柳州市
  • 广西壮族自治区

  • 桂林市
  • 广西壮族自治区

  • 梧州市
  • 广西壮族自治区

  • 河池市
  • 广西壮族自治区

  • 玉林市
  • 广西壮族自治区

  • 百色市
  • 广西壮族自治区

  • 贵港市
  • 广西壮族自治区

  • 贺州市
  • 广西壮族自治区

  • 钦州市
  • 广西壮族自治区

  • 防城港市
  • 新疆维吾尔自治区

  • 乌鲁木齐市
  • 新疆维吾尔自治区

  • 伊犁哈萨克自治州
  • 新疆维吾尔自治区

  • 克孜勒苏柯尔克孜自治州
  • 新疆维吾尔自治区

  • 克拉玛依市
  • 新疆维吾尔自治区

  • 博尔塔拉蒙古自治州
  • 新疆维吾尔自治区

  • 吐鲁番市
  • 新疆维吾尔自治区

  • 和田地区
  • 新疆维吾尔自治区

  • 哈密市
  • 新疆维吾尔自治区

  • 喀什地区
  • 新疆维吾尔自治区

  • 塔城地区
  • 新疆维吾尔自治区

  • 巴音郭楞蒙古自治州
  • 新疆维吾尔自治区

  • 昌吉回族自治州
  • 新疆维吾尔自治区

  • 自治区直辖县级行政区划
  • 新疆维吾尔自治区

  • 阿克苏地区
  • 新疆维吾尔自治区

  • 阿勒泰地区
  • 江苏省

  • 南京市
  • 江苏省

  • 南通市
  • 江苏省

  • 宿迁市
  • 江苏省

  • 常州市
  • 江苏省

  • 徐州市
  • 江苏省

  • 扬州市
  • 江苏省

  • 无锡市
  • 江苏省

  • 泰州市
  • 江苏省

  • 淮安市
  • 江苏省

  • 盐城市
  • 江苏省

  • 苏州市
  • 江苏省

  • 连云港市
  • 江苏省

  • 镇江市
  • 江西省

  • 上饶市
  • 江西省

  • 九江市
  • 江西省

  • 南昌市
  • 江西省

  • 吉安市
  • 江西省

  • 宜春市
  • 江西省

  • 抚州市
  • 江西省

  • 新余市
  • 江西省

  • 景德镇市
  • 江西省

  • 萍乡市
  • 江西省

  • 赣州市
  • 江西省

  • 鹰潭市
  • 河北省

  • 保定市
  • 河北省

  • 唐山市
  • 河北省

  • 廊坊市
  • 河北省

  • 张家口市
  • 河北省

  • 承德市
  • 河北省

  • 沧州市
  • 河北省

  • 石家庄市
  • 河北省

  • 秦皇岛市
  • 河北省

  • 衡水市
  • 河北省

  • 邢台市
  • 河北省

  • 邯郸市
  • 河南省

  • 三门峡市
  • 河南省

  • 信阳市
  • 河南省

  • 南阳市
  • 河南省

  • 周口市
  • 河南省

  • 商丘市
  • 河南省

  • 安阳市
  • 河南省

  • 平顶山市
  • 河南省

  • 开封市
  • 河南省

  • 新乡市
  • 河南省

  • 洛阳市
  • 河南省

  • 漯河市
  • 河南省

  • 濮阳市
  • 河南省

  • 焦作市
  • 河南省

  • 省直辖县级行政区划
  • 河南省

  • 许昌市
  • 河南省

  • 郑州市
  • 河南省

  • 驻马店市
  • 河南省

  • 鹤壁市
  • 浙江省

  • 丽水市
  • 浙江省

  • 台州市
  • 浙江省

  • 嘉兴市
  • 浙江省

  • 宁波市
  • 浙江省

  • 杭州市
  • 浙江省

  • 温州市
  • 浙江省

  • 湖州市
  • 浙江省

  • 绍兴市
  • 浙江省

  • 舟山市
  • 浙江省

  • 衢州市
  • 浙江省

  • 金华市
  • 海南省

  • 三亚市
  • 海南省

  • 三沙市
  • 海南省

  • 儋州市
  • 海南省

  • 海口市
  • 海南省

  • 省直辖县级行政区划
  • 湖北省

  • 十堰市
  • 湖北省

  • 咸宁市
  • 湖北省

  • 孝感市
  • 湖北省

  • 宜昌市
  • 湖北省

  • 恩施土家族苗族自治州
  • 湖北省

  • 武汉市
  • 湖北省

  • 省直辖县级行政区划
  • 湖北省

  • 荆州市
  • 湖北省

  • 荆门市
  • 湖北省

  • 襄阳市
  • 湖北省

  • 鄂州市
  • 湖北省

  • 随州市
  • 湖北省

  • 黄冈市
  • 湖北省

  • 黄石市
  • 湖南省

  • 娄底市
  • 湖南省

  • 岳阳市
  • 湖南省

  • 常德市
  • 湖南省

  • 张家界市
  • 湖南省

  • 怀化市
  • 湖南省

  • 株洲市
  • 湖南省

  • 永州市
  • 湖南省

  • 湘潭市
  • 湖南省

  • 湘西土家族苗族自治州
  • 湖南省

  • 益阳市
  • 湖南省

  • 衡阳市
  • 湖南省

  • 邵阳市
  • 湖南省

  • 郴州市
  • 湖南省

  • 长沙市
  • 甘肃省

  • 临夏回族自治州
  • 甘肃省

  • 兰州市
  • 甘肃省

  • 嘉峪关市
  • 甘肃省

  • 天水市
  • 甘肃省

  • 定西市
  • 甘肃省

  • 平凉市
  • 甘肃省

  • 庆阳市
  • 甘肃省

  • 张掖市
  • 甘肃省

  • 武威市
  • 甘肃省

  • 甘南藏族自治州
  • 甘肃省

  • 白银市
  • 甘肃省

  • 酒泉市
  • 甘肃省

  • 金昌市
  • 甘肃省

  • 陇南市
  • 福建省

  • 三明市
  • 福建省

  • 南平市
  • 福建省

  • 厦门市
  • 福建省

  • 宁德市
  • 福建省

  • 泉州市
  • 福建省

  • 漳州市
  • 福建省

  • 福州市
  • 福建省

  • 莆田市
  • 福建省

  • 龙岩市
  • 西藏自治区

  • 山南市
  • 西藏自治区

  • 拉萨市
  • 西藏自治区

  • 日喀则市
  • 西藏自治区

  • 昌都市
  • 西藏自治区

  • 林芝市
  • 西藏自治区

  • 那曲市
  • 西藏自治区

  • 阿里地区
  • 贵州省

  • 六盘水市
  • 贵州省

  • 安顺市
  • 贵州省

  • 毕节市
  • 贵州省

  • 贵阳市
  • 贵州省

  • 遵义市
  • 贵州省

  • 铜仁市
  • 贵州省

  • 黔东南苗族侗族自治州
  • 贵州省

  • 黔南布依族苗族自治州
  • 贵州省

  • 黔西南布依族苗族自治州
  • 辽宁省

  • 丹东市
  • 辽宁省

  • 大连市
  • 辽宁省

  • 抚顺市
  • 辽宁省

  • 朝阳市
  • 辽宁省

  • 本溪市
  • 辽宁省

  • 沈阳市
  • 辽宁省

  • 盘锦市
  • 辽宁省

  • 营口市
  • 辽宁省

  • 葫芦岛市
  • 辽宁省

  • 辽阳市
  • 辽宁省

  • 铁岭市
  • 辽宁省

  • 锦州市
  • 辽宁省

  • 阜新市
  • 辽宁省

  • 鞍山市
  • 重庆市

  • 重庆市

  • 市辖区
  • 陕西省

  • 咸阳市
  • 陕西省

  • 商洛市
  • 陕西省

  • 安康市
  • 陕西省

  • 宝鸡市
  • 陕西省

  • 延安市
  • 陕西省

  • 榆林市
  • 陕西省

  • 汉中市
  • 陕西省

  • 渭南市
  • 陕西省

  • 西安市
  • 陕西省

  • 铜川市
  • 青海省

  • 果洛藏族自治州
  • 青海省

  • 海东市
  • 青海省

  • 海北藏族自治州
  • 青海省

  • 海南藏族自治州
  • 青海省

  • 海西蒙古族藏族自治州
  • 青海省

  • 玉树藏族自治州
  • 青海省

  • 西宁市
  • 青海省

  • 黄南藏族自治州
  • 黑龙江省

  • 七台河市
  • 黑龙江省

  • 伊春市
  • 黑龙江省

  • 佳木斯市
  • 黑龙江省

  • 双鸭山市
  • 黑龙江省

  • 哈尔滨市
  • 黑龙江省

  • 大兴安岭地区
  • 黑龙江省

  • 大庆市
  • 黑龙江省

  • 牡丹江市
  • 黑龙江省

  • 绥化市
  • 黑龙江省

  • 鸡西市
  • 黑龙江省

  • 鹤岗市
  • 黑龙江省

  • 黑河市
  • 黑龙江省

  • 齐齐哈尔市