HLSL-High Level Shader Language

优点

用来书写Vertex Shader和Pixel Shader程序的代码,语法类似于C/C++,在DirectX 8.x的时代,Shader程序都是用低级Shader汇编语言编写的,姑且称之为LLSL吧,HLSL与之相比具有以下优点:

  • 更高的生产力,使用HLSL编程更快更容易,使我们有更多的时间关注与算法而不是编码
  • 更好的可读性,使用HLSH编写的程序更易读,易调试及维护
  • 编译器将生成更加高效的汇编代码
  • 可以将同一份代码编译成任何可用的Shader版本,但是用LLSL则必须按不同版本编写代码

如果你的显卡不支持Shader的话,那么可以使用REF Device模拟,这样可以得到正确的结果,但是速度非常慢

编写Shader代码

你可以将Shader代码写入到你的程序中,但是为了更方便,更模块化,通常将Shader程序放在单独的文件里,比如记事本,然后使用D3DXCompileShaderFromFile函数来编译它,使用记事本写Shader程序可能不太方便,以前微软提供编写Shader的工具,在DirectX SDK当中,但是现在不支持了,大家可以用AMD的RenderMonkey来编写。

一般的Shader程序包含以下几个部分

  • 全局变量-viewprojmatrix, color等
  • 输入结构和输出结构-VS_INPUT, VS_OUTPUT
  • 入口函数-Main, note the name is not mandatory, you can used any valid function name

常量表

每个Shader程序都有一个常量表来存储它的变量。可以用ID3DXConstantTable接口访问长量表,可以设置Shader程序中的全局变量值

实战-一个简单的Shader程序

下面我们就来看看如何编写一个Shader程序,我们还以茶壶为例,看看如何用Shader绘制一个蓝色的茶壶,学习如何用Shader处理颜色,这个例子简单的不能再简单,但是,它确实能反映如何使用Shader。首先用VS建立一个Win32工程,添加必要的框架代码,主要是创建窗口,简单的消息处理以及初始化D3D等,如下

  1 #include <d3dx9.h>
  2 
  3 LPDIRECT3D9             g_pD3D            = NULL ; // Used to create the D3DDevice
  4 LPDIRECT3DDEVICE9       g_pd3dDevice    = NULL ; // Our rendering device
  5 
  6 HRESULT InitD3D( HWND hWnd )
  7 {
  8     // Create the D3D object, which is needed to create the D3DDevice.
  9     if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
 10         return E_FAIL;
 11 
 12     D3DPRESENT_PARAMETERS d3dpp; 
 13     ZeroMemory( &d3dpp, sizeof(d3dpp) );
 14     d3dpp.Windowed = TRUE;
 15     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
 16     d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
 17 
 18     // Create device
 19     if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
 20         D3DCREATE_SOFTWARE_VERTEXPROCESSING,
 21         &d3dpp, &g_pd3dDevice ) ) )
 22     {
 23         return E_FAIL;
 24     }
 25 
 26     return S_OK;
 27 }
 28 
 29 VOID Cleanup()
 30 {
 31     if( g_pd3dDevice != NULL) 
 32         g_pd3dDevice->Release();
 33 
 34     if( g_pD3D != NULL)
 35         g_pD3D->Release();
 36 }
 37 
 38 VOID Render()
 39 {
 40     if( NULL == g_pd3dDevice )
 41         return;
 42 
 43     // Clear the back-buffer to a RED color
 44     g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
 45 
 46     // Begin the scene
 47     if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
 48     {
 49         // Rendering of scene objects can happen here
 50 
 51         // End the scene
 52         g_pd3dDevice->EndScene();
 53     }
 54 
 55     // Present the back-buffer contents to the display
 56     g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
 57 }
 58 
 59 LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
 60 {
 61     switch( msg )
 62     {
 63     case WM_KEYDOWN:
 64         {
 65             switch( wParam )
 66             {
 67             case VK_ESCAPE:
 68                 SendMessage( hWnd, WM_CLOSE, 0, 0 );
 69                 break ;
 70             default:
 71                 break ;
 72             }
 73         }
 74         break ;
 75 
 76     case WM_DESTROY:
 77         Cleanup();
 78         PostQuitMessage( 0 );
 79         return 0;
 80     }
 81 
 82     return DefWindowProc( hWnd, msg, wParam, lParam );
 83 }
 84 
 85 INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
 86 {
 87     // Register the window class
 88     WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, 
 89         GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
 90         L"D3D Tutorial", NULL };
 91     RegisterClassEx( &wc );
 92 
 93     // Create the application's window
 94     HWND hWnd = CreateWindow( L"D3D Tutorial", L"D3D Tutorial 01: CreateDevice", 
 95         WS_OVERLAPPEDWINDOW , 0, 0, 800, 600,
 96         NULL, NULL, wc.hInstance, NULL );
 97 
 98     // Initialize Direct3D
 99     if( SUCCEEDED( InitD3D( hWnd ) ) )
100     { 
101         // Show the window
102         ShowWindow( hWnd, SW_SHOWDEFAULT );
103         UpdateWindow( hWnd );
104 
105         // Enter the message loop
106         MSG    msg ; 
107         ZeroMemory( &msg, sizeof(msg) );
108         PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );
109 
110         while (msg.message != WM_QUIT)  
111         {
112             if( PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE) != 0)
113             {
114                 TranslateMessage (&msg) ;
115                 DispatchMessage (&msg) ;
116             }
117             else // Render the game if no message to process
118             {
119                 Render() ;
120             }
121         }
122     }
123 
124     UnregisterClass( L"D3D Tutorial", wc.hInstance );
125     return 0;
126 }

然后按照下面的步骤绘制一个茶壶

1.在程序头部添加茶壶对应的全局变量

1 ID3DXMesh*                g_pMesh                = NULL ;

2.在InitD3D函数尾部(返回语句之前)创建绘制茶壶的代码

1  D3DXCreateTeapot(g_pd3dDevice, &g_pMesh, NULL) ;

3. 在Render函数中添加绘制茶壶的代码,位于BeginScene和EndScene之间

1 g_pMesh->DrawSubset(0) ;

4.在Cleanup函数中清除茶壶对应的mesh

1 if(g_pMesh != NULL)
2     g_pMesh->Release() ;

下面编写Shader程序,打开记事本,输入如下代码,代码很简单-略加解释,ViewProjMatrix对应是view matrix和projection matrix的乘积,Blue是顶点颜色,input只包含一个信息,顶点位置,output包含两个信息,顶点的位置和颜色,在main函数中,将顶点的位置由local坐标系变换到投影空间,将颜色设置为蓝色,就这么简单。

 1 
 2 matrix ViewProjMatrix;
 3 vector Blue = {0.0f, 0.0f, 1.0f, 0.0f} ;
 4 
 5 struct VS_INPUT
 6 {
 7     vector position : POSITION;
 8 };
 9 
10 struct VS_OUTPUT
11 {
12     vector position : POSITION;
13     vector diffuse  : COLOR;
14 };
15 
16 
17 VS_OUTPUT Main(VS_INPUT input)
18 {
19     VS_OUTPUT output = (VS_OUTPUT)0;
20 
21     output.position = mul(input.position, ViewProjMatrix);
22 
23     output.diffuse = Blue ;
24     
25     return output;
26 }
27 
28 

回到主程序中,添加全局变量g_pVertexShader用来保存创建的shader

1 IDirect3DVertexShader9*    g_pVertexShader        = NULL ;

添加全局变量g_pConstantTable用来保存Shader对应的常量表,有了常量表就可以存取和修改shader中的变量

1 ID3DXConstantTable*        g_pConstantTable    = NULL ;

添加一个变量句柄来存取shader中对应的ViewProjMatrix

1 D3DXHANDLE ViewProjMatrixHanle = 0 ;

添加函数PrepareShader,这个函数负责从文件编译shader,创建shader,设置shader中的变量等

 1 bool PrepareShader()
 2 {
 3     ID3DXBuffer *shader ;
 4     ID3DXBuffer *errorBuffer ;
 5     
 6     // Compile shader from file
 7     HRESULT hr = D3DXCompileShaderFromFileA("Shader.txt", 0, 0, "Main", "vs_1_1", 
 8         D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY, &shader, &errorBuffer, &g_pConstantTable) ;
 9 
10     // error handling
11     // output compile error message
12     if( errorBuffer )
13     {
14         MessageBoxA(0, (char*)errorBuffer->GetBufferPointer(), 0, 0);
15         errorBuffer->Release() ;
16     }
17 
18     // compile failed
19     if(FAILED(hr))
20     {
21         MessageBox(0, L"D3DXCompileShaderFromFile() - FAILED", 0, 0);
22         return false;
23     }
24 
25     // Create shader
26     hr = g_pd3dDevice->CreateVertexShader((DWORD*)shader->GetBufferPointer(), &g_pVertexShader) ;
27 
28     // create failed
29     if(FAILED(hr))
30     {
31         MessageBox(0, L"CreateVertexShader - FAILED", 0, 0);
32         return false;
33     }
34 
35     shader->Release() ;
36 
37     // map handle to variable in shader
38     ViewProjMatrixHanle = g_pConstantTable->GetConstantByName(0, "ViewProjMatrix") ;
39 }
40 

最后一行将shader中的变量ViewProjMatrix与ViewProjMatrixHandle相关联,这样接下来就可以用ViewProjMatrixHandle来存取和设置ViewProjMatrix了。注意,GetConstantByName函数的第二个参数是一个字符串,用来表示要获取的变量名字,这个名字必须与Shader文件中指定的名字一样才行,否则的话不起作用,也就是说Shader文件中一定有一个名为ViewProjectMatrix的变量。

添加函数SetupMatrix

这个函数负责设置view matrix, projection matrix, 并将二者的乘积赋值给shader中的ViewProjMatrix以便完成shader中的运算

 1 void SetupMatrix()
 2 {
 3     // set view
 4     D3DXVECTOR3 eyePt(0.0f, 0.0f, -10.0f) ;
 5     D3DXVECTOR3 upVec(0.0f, 1.0f, 0.0f) ;
 6     D3DXVECTOR3 lookCenter(0.0f, 0.0f, 0.0f) ;
 7 
 8     D3DXMATRIX view ;
 9     D3DXMatrixLookAtLH(&view, &eyePt, &lookCenter, &upVec) ;
10 
11     // set projection
12     D3DXMATRIX proj ;
13     D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI / 4, 1.0f, 1.0f, 1000.0f) ;
14 
15     D3DXMATRIX viewproj = view * proj ;
16     g_pConstantTable->SetMatrix(g_pd3dDevice, ViewProjMatrixHanle, &viewproj) ;
17 
18     // this line is mandatory
19     g_pConstantTable->SetDefaults(g_pd3dDevice);
20 }

注意最后一行很重要,他是用来设置常量表中所有变量的默认值的,很多时候如果不加这一句,窗口中将看不到任何东西!还有要在InitD3D函数中禁用光照效果,因为我们是自己设置颜色

1 g_pd3dDevice->SetRenderState( D3DRS_LIGHTING , FALSE ); 

最后,也是最重要的,在Render函数中设置shader,只有这样,它才能生效

1 g_pd3dDevice->SetVertexShader(g_pVertexShader) ;

程序结束后,在Cleanup函数中清除常量表和shader

1 if(g_pConstantTable != NULL)
2     g_pConstantTable->Release() ;

4 if(g_pVertexShader != NULL)
5     g_pVertexShader->Release() ;

好了,大功告成,现在编译并运行这个程序,你将看到一个蓝色的茶壶!

完整源代码

  1 #include <d3dx9.h>
  2 
  3 LPDIRECT3D9             g_pD3D                = NULL ; // Used to create the D3DDevice
  4 LPDIRECT3DDEVICE9       g_pd3dDevice        = NULL ; // Our rendering device
  5 ID3DXMesh*                g_pMesh                = NULL ; // Hold the teapot
  6 IDirect3DVertexShader9*    g_pVertexShader        = NULL ; // vertext shader
  7 ID3DXConstantTable*        g_pConstantTable    = NULL ; // shader constant table
  8 
  9 // variable handle in shader file
 10 D3DXHANDLE ViewProjMatrixHanle = 0 ;
 11 
 12 HRESULT InitD3D( HWND hWnd )
 13 {
 14     // Create the D3D object, which is needed to create the D3DDevice.
 15     if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
 16         return E_FAIL;
 17 
 18     D3DPRESENT_PARAMETERS d3dpp; 
 19     ZeroMemory( &d3dpp, sizeof(d3dpp) );
 20     d3dpp.Windowed = TRUE;
 21     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
 22     d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
 23 
 24     // Create device
 25     if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
 26         D3DCREATE_SOFTWARE_VERTEXPROCESSING,
 27         &d3dpp, &g_pd3dDevice ) ) )
 28     {
 29         return E_FAIL;
 30     }
 31 
 32     //g_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);   
 33     g_pd3dDevice->SetRenderState( D3DRS_LIGHTING , FALSE );   
 34 
 35     D3DXCreateTeapot(g_pd3dDevice, &g_pMesh, NULL) ;
 36 
 37     return S_OK;
 38 }
 39 
 40 VOID Cleanup()
 41 {
 42     if( g_pd3dDevice != NULL) 
 43         g_pd3dDevice->Release();
 44 
 45     if( g_pD3D != NULL)
 46         g_pD3D->Release();
 47 
 48     if(g_pMesh != NULL)
 49         g_pMesh->Release() ;
 50 
 51     if(g_pConstantTable != NULL)
 52         g_pConstantTable->Release() ;
 53 
 54     if(g_pVertexShader != NULL)
 55         g_pVertexShader->Release() ;
 56 }
 57 
 58 bool PrepareShader()
 59 {
 60     ID3DXBuffer *shader ;
 61     ID3DXBuffer *errorBuffer ;
 62     
 63     // Compile shader from file
 64     HRESULT hr = D3DXCompileShaderFromFileA("Shader.txt", 0, 0, "Main", "vs_1_1", 
 65         D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY, &shader, &errorBuffer, &g_pConstantTable) ;
 66 
 67     // error handling
 68     // output compile error message
 69     if( errorBuffer )
 70     {
 71         MessageBoxA(0, (char*)errorBuffer->GetBufferPointer(), 0, 0);
 72         errorBuffer->Release() ;
 73     }
 74 
 75     // compile failed
 76     if(FAILED(hr))
 77     {
 78         MessageBox(0, L"D3DXCompileShaderFromFile() - FAILED", 0, 0);
 79         return false;
 80     }
 81 
 82     // Create shader
 83     hr = g_pd3dDevice->CreateVertexShader((DWORD*)shader->GetBufferPointer(), &g_pVertexShader) ;
 84 
 85     // create failed
 86     if(FAILED(hr))
 87     {
 88         MessageBox(0, L"CreateVertexShader - FAILED", 0, 0);
 89         return false;
 90     }
 91 
 92     shader->Release() ;
 93 
 94     // map handle to variable in shader
 95     ViewProjMatrixHanle = g_pConstantTable->GetConstantByName(0, "ViewProjMatrix") ;
 96 }
 97 
 98 void SetupMatrix()
 99 {
100     // set view
101     D3DXVECTOR3 eyePt(0.0f, 0.0f, -10.0f) ;
102     D3DXVECTOR3 upVec(0.0f, 1.0f, 0.0f) ;
103     D3DXVECTOR3 lookCenter(0.0f, 0.0f, 0.0f) ;
104 
105     D3DXMATRIX view ;
106     D3DXMatrixLookAtLH(&view, &eyePt, &lookCenter, &upVec) ;
107 
108     // set projection
109     D3DXMATRIX proj ;
110     D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI / 4, 1.0f, 1.0f, 1000.0f) ;
111 
112     D3DXMATRIX viewproj = view * proj ;
113     g_pConstantTable->SetMatrix(g_pd3dDevice, ViewProjMatrixHanle, &viewproj) ;
114 
115     // this line is mandatory
116     g_pConstantTable->SetDefaults(g_pd3dDevice);
117 }
118 
119 VOID Render()
120 {
121     if(!PrepareShader())
122         return ;
123 
124     SetupMatrix() ;
125 
126     // Clear the back-buffer to a RED color
127     g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
128 
129     // Begin the scene
130     if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
131     {
132         // Rendering of scene objects can happen here
133         g_pd3dDevice->SetVertexShader(g_pVertexShader) ;
134 
135         g_pMesh->DrawSubset(0) ;
136         // End the scene
137         g_pd3dDevice->EndScene();
138     }
139 
140     // Present the back-buffer contents to the display
141     g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
142 }
143 
144 LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
145 {
146     switch( msg )
147     {
148     case WM_KEYDOWN:
149         {
150             switch( wParam )
151             {
152             case VK_ESCAPE:
153                 SendMessage( hWnd, WM_CLOSE, 0, 0 );
154                 break ;
155             default:
156                 break ;
157             }
158         }
159         break ;
160 
161     case WM_DESTROY:
162         Cleanup();
163         PostQuitMessage( 0 );
164         return 0;
165     }
166 
167     return DefWindowProc( hWnd, msg, wParam, lParam );
168 }
169 
170 INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
171 {
172     // Register the window class
173     WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, 
174         GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
175         L"D3D Tutorial", NULL };
176     RegisterClassEx( &wc );
177 
178     // Create the application's window
179     HWND hWnd = CreateWindow( L"D3D Tutorial", L"Simple shader", 
180         WS_OVERLAPPEDWINDOW , 0, 0, 600, 600,
181         NULL, NULL, wc.hInstance, NULL );
182 
183     // Initialize Direct3D
184     if( SUCCEEDED( InitD3D( hWnd ) ) )
185     { 
186         // Show the window
187         ShowWindow( hWnd, SW_SHOWDEFAULT );
188         UpdateWindow( hWnd );
189 
190         // Enter the message loop
191         MSG    msg ; 
192         ZeroMemory( &msg, sizeof(msg) );
193         PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );
194 
195         while (msg.message != WM_QUIT)  
196         {
197             if( PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE) != 0)
198             {
199                 TranslateMessage (&msg) ;
200                 DispatchMessage (&msg) ;
201             }
202             else // Render the game if no message to process
203             {
204                 Render() ;
205             }
206         }
207     }
208 
209     UnregisterClass( L"D3D Tutorial", wc.hInstance );
210     return 0;
211 }
212 
213 
214 
215 

happy coding!

作者:zdd
出处:http://www.cnblogs.com/graphics/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

HLSL-高级着色语言简介【转】的更多相关文章

  1. DirectX9:高级着色语言(HLSL)

    一.简介 高级着色语言(High)可以编写顶点着色器和像素着色器,取代固定功能流水线中的部分功能,在图形卡的GPU(Graphics Processing Unit,图形处理单元)中执行 注意:如果图 ...

  2. 有关OpenGL着色语言(一)

    刚接触OpenGL着色语言...,不定期增加内容 1.OpenGL着色语言(GLSL)是什么? 用于OpenGL的面向过程的高级着色语言,是近年来图形编程领域中出现的最重要的新型开发技术,使用Open ...

  3. Obj模型功能完善(物体材质,光照,法线贴图).Cg着色语言+OpenTK+F#实现.

    这篇文章给大家讲Obj模型里一些基本功能的完善,包含Cg着色语言,矩阵转换,光照,多重纹理,法线贴图的运用. 在上篇中,我们用GLSL实现了基本的phong光照,这里用Cg着色语言来实现另一钟Blin ...

  4. WPF 像素着色器入门:使用 Shazzam Shader Editor 编写 HLSL 像素着色器代码

    原文:WPF 像素着色器入门:使用 Shazzam Shader Editor 编写 HLSL 像素着色器代码 HLSL,High Level Shader Language,高级着色器语言,是 Di ...

  5. 计算机程序和C++语言简介

    C++程序设计 第一章 计算机程序和C++语言简介 1.计算机是一台能够存储并处理数据的电子设备,包含硬件和软件两部分. 2.计算机硬件由: 1)中央处理单元(Central Processing U ...

  6. GO 语言简介(网摘)

    GO 语言简介 原文出处:[陈皓 coolshell] Hello World 文件名 HELLO.GO package main //声明本文件的package名 import "fmt& ...

  7. 第一章 Python程序语言简介

    第一节 Python概述 1. 什么是Python Python是一种 解释型.面向对象.动态数据类型 的高级程序设计语言.由Guido van Rossum与1989年发明,第一个公开发行版本发行于 ...

  8. Python 语言简介

    Python是一种计算机程序设计语言.你可能已经听说过很多种流行的编程语言,比如非常难学的C语言,非常流行的Java语言,适合初学者的Basic语言,适合网页编程的JavaScript语言等等. 那P ...

  9. Go 语言简介(下)— 特性

    希望你看到这篇文章的时候还是在公交车和地铁上正在上下班的时间,我希望我的这篇文章可以让你利用这段时间了解一门语言.当然,希望你不会因为看我的文章而错过站.呵呵. 如果你还不了解Go语言的语法,还请你移 ...

随机推荐

  1. SVN客户端的安装和使用

    ----------------------siwuxie095 SVN 客户端的安装 1.SVN 客户端,选择 TortoiseSVN,下载链接: https://tortoisesvn.net/d ...

  2. Apache Cordova vs Adobe PhoneGap: the differences and which one to use

    http://www.makehybridapps.com/2014/06/09/cordova-vs-phonegap-the-differences-and-which-one-to-use/

  3. instanceof用法及本质:

    import static java.lang.System.*; public class InstanceofTest{ public static void main(String[] args ...

  4. iOS.ObjC.Basic-Knowledge

    1. ObjC的基础 2. ObjC2.0中的编译指令 3. ObjC Runtime 4. ObjC Object Model 5. ObjC的新语法 6. FQA 1. ObjC的基础 2. Ob ...

  5. python编辑excel

    转: http://www.cnblogs.com/lhj588/archive/2012/01/06/2314181.html

  6. Alluxio/Tachyon如何发挥lineage的作用?

    在Spark的RDD中引入过lineage这一概念.指的是RDD之间的依赖.而Alluxio则使用lineage来表示文件之间的依赖.在代码层面,指的是fileID之间的依赖. 代码中的注释指出: * ...

  7. 我的UI启蒙之路

    为什么叫UI启蒙之路呢? 我没有学过美术,也不懂设计,但是有的时候也许就是一种命中注定吧,让我知道了UI,并且一发不可收拾的爱上了它. 具体情况是这样的: 我毕业于电力学校,是一名不折不扣的工科生,专 ...

  8. laravel使用$errors提取错误信息

    1.控制器 2.模板

  9. Laravel 5.4+Vue.js 初体验:Laravel下配置运行Vue.js

    生产材料PHP:PHP 5.6+Laravel 5.4:https://github.com/laravel/laravel/releases/Composer:http://getcomposer. ...

  10. 低配NOSQL

    东西写的太简单了 都不好意思说是NOSQL 其实就是STL 的map容器记录了写入的信息 解析了下数据仅此. 分析的时候想了很多 比如学习redis的自写hash,动态调整hash表容量. 比如右值或 ...