First we look at the project result: A picture that looks “grey”.

Below is the original Picture.

So let’s see how to do it. First you had to know some knowledge about “DirectX Texture”. If you don’t, you can see the article “DirectX 9.0 C++ tutorial Texture ” Firstly.

Today’s topic is HLSL and Pixel Shader, it’s a some kind difficult topic.

Introduction:

HLSL is an abbreviation for “High-LevelShading Language”. We will use HLSL to write a small Pixel Shade program.Shortly, vertex and pixel shaders are small custom programs we write, executedon the graphic card’s GPU, that replace a portion of the “fixed  function pipeline”. By replacing a section of the fixed function pipeline with our own custom shader program, we obtain a huge amount of flexibility in the graphical effects that we can achieve. We are no longer limited to predefined “fixed” operations.

HLSL’s grammar is similar to C or C++; we can learn it very quickly.

Writing an HLSL Shader

We can write the code to our HLSL shaders directly into our application source files as a long character string. However,it is more convenient and modular to separate the shader code from the application code. For this reason, we write our shaders in Notepad and save them as regular ASCII text files. Then we use the D3DXComplileShaderFromFile function to compile our shaders.

This sample uses a pixel shader as an example.

//
// globals
//
sampler BaseTex;//
// input structures
//
struct PS_INPUT
{float2 base      : TEXCOORD;
};
//
// output structures
//
struct PS_OUTPUT
{vector color : COLOR;
};//
//  Main Function
//
PS_OUTPUT Main(PS_INPUT input)
{// zero out members of outputPS_OUTPUT output = (PS_OUTPUT)0;vector b = tex2D(BaseTex,      input.base);// The core code, calculate the texel colors, so the picture will be look like "black and white"vector c = 0.3 * b.x + 0.59 * b.y + 0.11 * b.z ;output.color = c;return output;
}

Globals

First we instantiate a global variable:

sampler BaseTex;

Input and Output Structures

After the global variable is declared, we define two special structures, which we call the input and output structures.For pixel shaders, these structures define the texture data that our shader inputs and outputs, respectively.

struct PS_INPUT
{float2 base      : TEXCOORD;
};
struct PS_OUTPUT
{vector color : COLOR;
};

In this sample, the texture coordinate that we input into our pixel shader contains only a texture coordinate component.The texture coordinate that our shader outputs contains a color component.

The syntax “: COLOR” says that the vector color is used to describe the color of the output vertex.

Entry Point Function

As with a C++ program, every HLSL program has an entry point. In our sample shader, we call our entry point function Main; however, that name is not mandatory. The shader’s entry point function name can be any valid function name. The entry point function must have an input structure parameter, which is used to pass the input texture coordinate intoour shader. The entry point function must also return an output structure instance, which is used to output the manipulated vertex from our shader.

Compiling an HLSL Shader

The Constant Table

Every shader has a constant table that is used to store its variable. The D3DX library providers our application access to a shader’s constant table through the ID3DXConstantTable interface. Via this interface we can set variables in the shader source code from our application’s code.

Getting a Handle to a Constant

In order to set a particular variable in a shader from our application code, we need a way to refer to it. We can refer to a variable in the shader from our application with a D3DXHANDLE. The following method returns a D3DXHANDLE to avariable in the shader when given its name:

D3DXHANDLE ID3DXConstantTable::GetConstantByName(D3DXHANDLE hConstant, // scope of constantLPCSTR pName          // name of constant
);

For example, if the name of the variable in the shader is “BaseTex” and it was a top level parameter, we could write:

D3DXHANDLE h0;

H0 = ConstTable->GetConstantByName(0, “BaseTex”);

Setting Constants

Once our application has a D3DXHANDLE that refers to a particular variable in the shader code, we can set that variable from our application using the ID3DXConstantTable::SetXXX methods, where theXXX is replaced by a type name to indicate the type of variable being set. Forexample, if the variable that we wish to set is a Sampler State, the method name would be SetSampleState.

Theg eneral syntax of the ID3DXConstantTable::SetXXX methods is of the form:

HRESULT ID3DXConstantTable::SetXXX(LPDIRECT3DDEVICE9 pDevice,D3DXHANDLE hConstant,XXX value
);

For example:

LPDIRECT3DDEVICE9       g_pd3dDevice;

D3DXCONSTANT_DESC BaseTexDesc;

g_pd3dDevice->SetSamplerState(BaseTexDesc.RegisterIndex,D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);

Compiling an HLSL Shader

We can compile a shader, which we have saved to a text file, using the following function:

HRESULT D3DXCompileShaderFromFile(LPCSTR               pSrcFile,CONST D3DXMACRO*     pDefines,LPD3DXINCLUDE        pInclude,LPCSTR               pFunctionName,LPCSTR               pTarget,DWORD                Flags,LPD3DXBUFFER*        ppShader,LPD3DXBUFFER*        ppErrorMsgs,LPD3DXCONSTANTTABLE* ppConstantTable
);
Here is an example call of D3DXCompileShaderFromFile:
//
// Compile shader
//ID3DXConstantTable* TransformConstantTable = 0;
ID3DXBuffer* shader      = 0;
ID3DXBuffer* errorBuffer = 0;hr = D3DXCompileShaderFromFile("hlslTexture.txt",0,0,"Main",             // entry point function name"ps_1_1",           // HLSL shader name D3DXSHADER_DEBUG,&shader,            // containing the created shader&errorBuffer,       // containing a listing of errors and warnings&TextCT);           // used to access shader constants
// output any error messages
if( errorBuffer )
{::MessageBox(0, (char*)errorBuffer->GetBufferPointer(), 0, 0);d3d::Release<ID3DXBuffer*>(errorBuffer);
}if (FAILED (hr))
{::MessageBox(0, "D3DXCreateEffectFromFile() - FAILED", 0, 0);return false;
}

Pixel Shader Inputs and outputs

Two things are input into a pixel shader:colors and texture coordinates. Both are per pixel. A per pixel texture coordinate is simply the (u,v) coordinates that specify the texel in the texture that is to be mapped to the pixel in question. Direct3D computes both colors and texture coordinates per pixel, from vertex colors and vertex texture coordinates, before entering the pixel shader. The number of colors and texture coordinates input into the pixel shader depends on how many colors and texture coordinates were output by the vertex shader. For example, if a vertex shader outputs two colors and three texture coordinates, then Direct3D will calculate two colors and three texture coordinates per pixel and input them into the pixel shader. We map the input colors and texture coordinates to variables inour pixel shader program using the semantic syntax. Using the previous example,we would write:

struct PS_INPUT
{vector c0 : COLOR0;vector c1 : COLOR1;float2 t0 : TEXCOORD0;float2 t1 : TEXCOORD1;float2 t2 : TEXCOORD2;
};
For output, a pixel shader outputs a single computed color value for the pixel:
struct PS_OUTPUT
{vector finalPixelColor : COLOR0;
};

Steps to Using a Pixel Shader

The following list outlines the steps necessary to create and use a pixel shader.

1.      Write and compile the pixel shader.

2.      Create an IDirect3DPixelShader9 interface to represent the pixel shader based on the compiled shader code.

3.      Enable the pixel shader with the IDirect3DDevice9::SetPixelShader method.

Of course, we have to destroy the pixel shader when we are done with it. The next few subsections go into these steps in more detail.

Writing and Compiling a Pixel Shader

We compile the shader using the D3DXCompileShaderFromFile function.

Creating a Pixel Shader

Once we have the compiled shader code, we can obtain a pointer to an IDirect3DPixelShader9 interface, which represents apixel shader, using the following method:

HRESULT IDirect3DDevice9::CreatePixelShader(CONST DWORD *pFunction,IDirect3DPixelShader9** ppShader
);

For example, suppose the variable shader is an ID3DXBuffer that contains the compiled shader code. Then to obtain an IDirect3DPixelShader9 interface, we would write:

IDirect3DPixelShader9* MultiTexPS = 0;
hr = Device->CreatePixelShader((DWORD*)shader->GetBufferPointer(),&MultiTexPS);

Setting a Pixel Shader

After we have obtained a point to an IDirect3DPixelShader9 interface that represents our pixel shader, we can enable it using the following method:

HRESULT IDirect3DDevice9::SetPixelShader(IDirect3DPixelShader9* pShader
);

The method takes a single parameter where we pass a point to the pixel shader that we wish to enable. We would write:

Device->SetPixelShader(MultiTexPS);

Destroying a Pixel Shader

As with all Direct3D interfaces, to clean them up we must call their Release method when we are finished with them.

The Sample Application Code

//-----------------------------------------------------------------------------
// File: Textures.cpp
// About "Using Pixel Shader"
// Copyright (c) Microsoft Corporation & Waitingfy.com. All rights reserved.
//-----------------------------------------------------------------------------
#include <Windows.h>
#include <mmsystem.h>
#include <d3dx9.h>
#include <strsafe.h>//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9             g_pD3D       = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // Our rendering device
LPDIRECT3DVERTEXBUFFER9 g_pVB        = NULL; // Buffer to hold vertices
LPDIRECT3DTEXTURE9      g_pTexture   = NULL; // Our TextureIDirect3DPixelShader9* TexPS = 0;            // Interface to encapsulate the functionality of a pixel shader
ID3DXConstantTable* TextCT = 0;              // Used to access the constant tableD3DXHANDLE BaseTexHandle = 0;
D3DXCONSTANT_DESC BaseTexDesc;               // A description of a constant in a constant table// A structure for out custom vertex type. And We added texture coordinates
struct CUSTOMVERTEX
{float x, y, z;unsigned long color;FLOAT       tu, tv;   //  texture coordinates
};// Compare to "Triangle" Example, Here add D3DFVF_TEX1
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Initializes Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{// Create the D3D objectif( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )return E_FAIL;// Set up the structure used to create the D3DDevice. Since we are now// using more complex geomitry, we will create a device with a zbuffer.D3DPRESENT_PARAMETERS d3dpp;ZeroMemory( &d3dpp, sizeof(d3dpp) );d3dpp.Windowed = TRUE;d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;d3dpp.EnableAutoDepthStencil = TRUE;d3dpp.AutoDepthStencilFormat = D3DFMT_D16;// Create the D3DDeviceif( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp, &g_pd3dDevice ) ) ){return E_FAIL;}// Turn off cullingg_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );// Turn off D3D lightingg_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );// Turn on the zbufferg_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );HRESULT hr = 0;ID3DXBuffer* shader = 0;ID3DXBuffer* errorBuffer = 0;// Compile shader from a filehr = D3DXCompileShaderFromFile("hlslTexture.txt",0,0,"Main",             // entry point function name"ps_1_1",           // HLSL shader name D3DXSHADER_DEBUG,&shader,            // containing the created shader&errorBuffer,       // containing a listing of errors and warnings&TextCT);           // used to access shader constantsif(errorBuffer){::MessageBox(0,(char*)errorBuffer->GetBufferPointer(), 0, 0);errorBuffer->Release();}if(FAILED(hr)){::MessageBox(0,"D3DXCompileShaderFromFile() - FAILED", 0, 0);return false;}// creates a pixel shaderhr = g_pd3dDevice->CreatePixelShader((DWORD*)shader->GetBufferPointer(),&TexPS);if(FAILED(hr)){::MessageBox(0,"CreateVertexShader - FAILED", 0, 0);return false;}shader->Release();// gets a constant BaseTexHandle = TextCT->GetConstantByName(0, "BaseTex");// set constant descriptionsUINT count;TextCT->GetConstantDesc(BaseTexHandle, &BaseTexDesc, &count);return S_OK;
}//-----------------------------------------------------------------------------
// Name: InitGeometry()
// Desc: Create the Textures and vertex buffers
//-----------------------------------------------------------------------------
HRESULT InitGeometry()
{HRESULT hr = 0;// create texturehr = D3DXCreateTextureFromFile( g_pd3dDevice, "objective-c.png", &g_pTexture );if(FAILED(hr)){MessageBox(NULL, "Could not find objective-c.png", "Textures.exe", MB_OK);return E_FAIL;   }// Initialize the vertices including texture coordinate CUSTOMVERTEX Vertices[] ={{ -1.0f, -1.0f, 0.0f, D3DCOLOR_XRGB(255,255,255),0,1 }, // x, y, z, rhw, color,tu,tv{ -1.0f, 1.0f, 0.0f, D3DCOLOR_XRGB(255,255,255), 0,0},{ 1.0f, -1.0f, 0.0f, D3DCOLOR_XRGB(255,255,255), 1,1},{ 1.0f, 1.0f, 0.0f, D3DCOLOR_XRGB(255,255,255), 1,0},};// Create the vertex bufferhr = g_pd3dDevice->CreateVertexBuffer(sizeof(Vertices),D3DUSAGE_WRITEONLY,D3DFVF_CUSTOMVERTEX,D3DPOOL_MANAGED,&g_pVB,0);if(hr){return E_FAIL;}// Filled with data from the custom verticesVOID* pVertices;if( FAILED( g_pVB->Lock( 0, sizeof(Vertices), (void**)&pVertices, 0 ) ) )return E_FAIL;memcpy( pVertices, Vertices, sizeof(Vertices) );g_pVB->Unlock();return S_OK;
}//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: Released all previously initialized objects
//-----------------------------------------------------------------------------
VOID Cleanup()
{if( g_pTexture != NULL )g_pTexture->Release();if( g_pVB != NULL )g_pVB->Release();if( g_pd3dDevice != NULL )g_pd3dDevice->Release();if( g_pD3D != NULL )g_pD3D->Release();if(TexPS != NULL )TexPS->Release();if(TextCT != NULL)TextCT->Release();
}//-----------------------------------------------------------------------------
// Name: SetupMatrices()
// Desc: Sets up the world, view, and projection transform matrices.
//-----------------------------------------------------------------------------
VOID SetupMatrices()
{// Rotate by the Y axisD3DXMATRIXA16 matWorld;D3DXMatrixIdentity( &matWorld );//remove the comments below to rotate the picture//D3DXMatrixRotationY( &matWorld, timeGetTime()/1000.0f );g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );// Set View Transformation Matrix. Including some carame informationD3DXVECTOR3 vEyePt( 0.0f, 0.0f,-2.5f );D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );D3DXMATRIXA16 matView;D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );// Set Transformation MatrixD3DXMATRIXA16 matProj;D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );}//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
VOID Render()
{// Clear the backbuffer and the zbuffer, Set color to blueg_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );// Begin the sceneif( SUCCEEDED( g_pd3dDevice->BeginScene() ) ){// Setup the world, view, and projection matricesSetupMatrices();g_pd3dDevice->SetPixelShader(TexPS);// Setting the texture to useg_pd3dDevice->SetTexture(BaseTexDesc.RegisterIndex, g_pTexture);g_pd3dDevice->SetSamplerState(BaseTexDesc.RegisterIndex, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);g_pd3dDevice->SetSamplerState(BaseTexDesc.RegisterIndex, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);g_pd3dDevice->SetSamplerState(BaseTexDesc.RegisterIndex, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);// Render the vertex buffer contentsg_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );// A rectangle made of two trianglesg_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2);// End the sceneg_pd3dDevice->EndScene();}// Present the backbuffer contents to the dispalyg_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{switch( msg ){case WM_DESTROY:Cleanup();PostQuitMessage( 0 );return 0;}return DefWindowProc( hWnd, msg, wParam, lParam );
}//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{// Register the window classWNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,GetModuleHandle(NULL), NULL, NULL, NULL, NULL,"D3D Tutorial", NULL };RegisterClassEx( &wc );// Create the application's windowHWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 05: Textures",WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,GetDesktopWindow(), NULL, wc.hInstance, NULL );// Initialize Direct3Dif( SUCCEEDED( InitD3D( hWnd ) ) ){// Create the scene geometryif( SUCCEEDED( InitGeometry() ) ){// Show the windowShowWindow( hWnd, SW_SHOWDEFAULT );UpdateWindow( hWnd );// Enter the message loopMSG msg;ZeroMemory( &msg, sizeof(msg) );while( msg.message!=WM_QUIT ){if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ){TranslateMessage( &msg );DispatchMessage( &msg );}elseRender();}}}UnregisterClass( "D3D Tutorial", wc.hInstance );return 0;
}

References:

1. <Introduction to 3D Game Programming with DirectX 9.0> Chapter 16:Introduction to the High-Level Shading Language,Chapter 18:Introduction to Pixel Shaders

2. DirectX 9.0 SDK's Tutorial 5: Using Texture Maps

3. HLSL初步知识讲解 http://download.csdn.net/detail/chengscga/3948392

Project Download:

HLSL+Pixel+Shader (www.Waitingfy.com Download)

http://www.waitingfy.com/?p=387

Illustrate a HLSL example by using Pixel Shade相关推荐

  1. HLSL 学习笔记1 vertex shader, pixel shader

    VERTEX SHADER 模板 //v2f 是输出结构,在前面定义了 v2f v(a2v In, uniform float4 lightPosition)//uniform 说明该数据来自shad ...

  2. Direct3D提高篇:HLSL编程实现PhotoShop滤镜效果(1)

    现在学习Direct3d/HLSL的人非常多,教程也非常多.因为硬件的水平在进步,所以可编程管道的处理能力也在不断的提高.从Direct3D 8开始,Direct3D中引入了可编程管道(Program ...

  3. HLSL的一些常见渲染特效的实现

    http://group.lehu.shu.edu.cn/Article.aspx?aid=147793 原文作者:潘李亮 xheartblue@163.com 关于学习,中国有句古话叫"学 ...

  4. D3D9 effect (hlsl)(转)

    转:http://blog.csdn.net/leonwei/article/details/8212800 effect其实整合了shader和render state的控制两大部分内容 9.1 e ...

  5. 在场景中添加光线——添加HLSL Vertex Shading

    问题 使用你配置好的光照,BasicEffect可以很好地绘制场景.但是,如果你想定义一些更酷的效果,首先要实现的就是正确的光照. 本教程中,你将学习如何编写一个基本的HLSL effect实现逐顶点 ...

  6. HLSL编译工具—FXC

    声明: © 2012 刘邓 hfutld@yeah.net. All rights reserved. 翻译说明: 1."/" 这个符号出现在我翻译一个单词或者词组不确定时可能的选 ...

  7. 正式宣布DXBC2GLSL,HLSL字节码到GLSL的编译器

    转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=2826 三年前,我就曾经计划过一个KlayGE的长期研发子项目,D3D11 HLSL字节码到G ...

  8. hlsl之ambient

    最简单的hlsl. effect code: //--------------------------------------------------------------------------- ...

  9. [推荐]HLSL编程实现PhotoShop滤镜效果

    本文原创版权归 潘李亮所有,如有转载,请按如下方式于明显位置标明原创作者及出处,以示尊重!! ===================================================== ...

最新文章

  1. linux tf命令,Linux系统命令介绍之vmstat命令详解
  2. 链路聚合_rhel7下的链路聚合配置
  3. Tomcat的设置1——设置根目录
  4. Typecho 新浪登陆插件 Sinauth
  5. MySQL trim()函数
  6. excel vb ppap_vb是什么平台-常见问题
  7. CPU可以跑多快?地球到火星的距离告诉你!
  8. weui上传组件的图片封装到formdata_自定义toast-ui富文本组件的图片黏贴上传
  9. android中自适应布局教程,Android实现自适应正方形GridView
  10. [Android实例教程] 教你如何拍照+相册选择图片+剪裁图片完整实现
  11. 函数重载与函数覆盖的区别(C++)
  12. c语言 fft程序,FFT算法的使用说明与C语言版实现源码
  13. origin matlab调用,origin与matlab使用教程
  14. redis命令之string类型mset命令用法详情
  15. Office2010安装出错(Error1406)
  16. 怎么入门学习Java编程
  17. 通过本地jedis连接远程服务器上的docker redis
  18. Android显示横幅样式通知
  19. GitHub Actions入门教程:自动化部署静态博客
  20. 字节员工收黑钱、操控抖音热榜,判刑了!

热门文章

  1. 终于知道META是什么意思了
  2. Mac电脑贵在何处?
  3. 换换二手交易平台成行业绿色环保标杆
  4. IMU误差模型简介及VINS使用说明
  5. SOLIDWORKS草图块功能的使用
  6. php求一个数的阶乘,PHP基于简单递归函数求一个数阶乘的方法示例
  7. gwas snp 和_gwas
  8. [转载]新浪杨栋漫画――梅西多纳……
  9. 技术动态 | GML如何做药物发现?奥尔胡斯大学最新《知识增强图机器学习在药物发现中的应用》综述...
  10. JAVA房屋中介管理计算机毕业设计Mybatis+系统+数据库+调试部署