青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當(dāng)自強(qiáng)而不息

頂點(diǎn)著色器入門(3)

新建網(wǎng)頁 1

作為第二個(gè)頂點(diǎn)著色器的例子,讓我們編寫兩個(gè)頂點(diǎn)著色器,它們以卡通風(fēng)格的繪畫方式對網(wǎng)格著色(shade輪廓勾勒(outline)。圖17.2展示了這一點(diǎn):

 

                       
               

注意:卡通渲染是一種特定類型的非寫實(shí)渲染(non-photorealistic rendering),有時(shí)被稱作風(fēng)格化渲染(stylistic rendering)。

雖然卡通渲染不適用于所有游戲,例如激烈的第一人稱射擊游戲,但是它仍然可以增強(qiáng)一些希望表現(xiàn)卡通感覺類型游戲的氣氛。此外,卡通渲染是漂亮的,并易于實(shí)現(xiàn)。讓我們好好的演示一個(gè)頂點(diǎn)著色器。

我們將卡通渲染分為兩步:

1.       卡通繪畫的特點(diǎn)是:在一個(gè)頂點(diǎn)到下一個(gè)頂點(diǎn)的強(qiáng)烈轉(zhuǎn)換時(shí),有少量的陰影強(qiáng)度級(jí)別;我們看一下這個(gè)卡通陰影(cartoon shading)。在圖17.2a)中,我們看到網(wǎng)絡(luò)著色使用了三種陰影強(qiáng)度(亮、中、暗),而且其間的過渡是不平滑的——不像圖17.2c),其明暗過渡是平滑的。

2.       卡通繪圖的主要特點(diǎn)是:在其外框上勾畫輪廓,如圖17.2b)所示。

這兩個(gè)步驟都需要其各自的頂點(diǎn)著色器。

 

17.5.1 卡通著色

要實(shí)現(xiàn)卡通著色,我們采用Lander20003月發(fā)表在Game Developer Magazine的文章“Shades of Disney: Opaquing a 3D World”中所描述的方法。我們創(chuàng)建一個(gè)帶強(qiáng)度級(jí)別的灰度紋理,它包含我們需要的不同的著色強(qiáng)度。圖17.3顯示了我們在樣例程序中使用的這個(gè)紋理。

然后在頂點(diǎn)著色器中,我們執(zhí)行標(biāo)準(zhǔn)漫反射光運(yùn)算(standard diffuse calculation dot product)來確定頂點(diǎn)法線N和光線向量L之間角度的余弦,用以確定頂點(diǎn)接收到多少光線:s=L·N

如果s0,就表示光線向量和頂點(diǎn)法線之間的角度大于90度,即該表面接收不到光線。因此,如果s0,我們就讓s0。所以s [0, 1]

現(xiàn)在,在通常的散射光照模型中,我們使用s來標(biāo)記顏色向量。這樣,頂點(diǎn)顏色的明暗取決于接收到的光照的數(shù)量:diffuseColor = s(r, g, b, a)

但是,這將會(huì)導(dǎo)致從亮到暗之間平滑的著色。這是與我們期望的卡通著色相反的。我們想要一種在幾個(gè)不同著色器間突然轉(zhuǎn)換顏色的效果(對卡通渲染來說,在24種著色器工作起來還是挺不錯(cuò)的)。

不使用s來標(biāo)記顏色向量,我們將使用s作為早先提到的強(qiáng)度紋理的u紋理坐標(biāo)——如圖17.3

注意:標(biāo)量(scalars必定是一個(gè)有效的紋理坐標(biāo),因?yàn)?span lang="EN-US">s [0, 1],這是通常的紋理坐標(biāo)區(qū)間。

按這種方式,頂點(diǎn)不會(huì)被平滑著色,而是間斷的。例如,強(qiáng)度紋理可能被分成3種著色,如圖17.4所示:

由圖17.4可以看出:若s [0, 0.33]則使用shader0著色,s [ 0.330.66]則使用shader1著色,s [0.66,1]則使用shader2著色。當(dāng)然,從這些著色的一種到另一種的過渡是不平滑的,這就賦予了我們期望的效果。

注意:我們還為卡通著色關(guān)閉了紋理過濾,因?yàn)檫@種過濾會(huì)試圖使著色過渡變平滑。這對于我們要求的不連續(xù)過渡是多余的。

17.5.2 卡通著色的頂點(diǎn)著色器代碼

我們現(xiàn)在介紹卡通著色的頂點(diǎn)著色器。這個(gè)著色器的主要任務(wù)只是根據(jù)s=L·N計(jì)算并設(shè)置紋理坐標(biāo)。注意觀察輸出結(jié)構(gòu),我們已經(jīng)增加了一個(gè)數(shù)據(jù)成員來存儲(chǔ)已被計(jì)算過的紋理坐標(biāo)。同時(shí)還需注意,我們?nèi)匀惠敵鲰旤c(diǎn)顏色,雖然我們不修改它,不過當(dāng)顏色與強(qiáng)度紋理組合起來的時(shí)候,便呈現(xiàn)出著色的效果。

     /*****************************************************************************************
      Vertex shader that lights geometry such it appears to be drawn in a cartoon style.
     *****************************************************************************************/

   
    matrix g_world_view;
    matrix g_world_view_proj;
   
    vector g_color;
    vector g_dir_to_light;
   
   
struct sVertexInput
    {
        vector position : POSITION;
        vector normal    : NORMAL;
    };
   
   
struct sVertexOutput
    {
        vector position : POSITION;
        float2 uv        : TEXCOORD;
        vector diffuse  : COLOR;
    };
   
   
    ////////////////////////////////////////////////////////////////////////////////////////////////
   

    sVertexOutput main(sVertexInput input)
    {
        sVertexOutput output = (sVertexOutput) 0;
   
        
// transforma vertex position to homogenous clip space
   
        output.position = mul(input.position, g_world_view_proj);
   
        
// Transform lights and normals to view space, set w components to zero since we're transforming vectors.
        // Assume there are no scalings in the world matrix as well.
   

        g_dir_to_light.w = 0.0f;
        input.normal.w   = 0.0f;
   
        g_dir_to_light = mul(g_dir_to_light, g_world_view);
        input.normal   = mul(input.normal,   g_world_view);
   
        
// compute the 1D texture coordinate for catoon rendering
   

        
float u = dot(g_dir_to_light, input.normal);
   
        
// Clamp to zero if u is negative because u negative implies the angle between the light and normal 
        // is greater than 90 degrees.  And if that is true then the surface receives no light.
   
    if(u < 0.0f)
            u = 0.0f;
   
        
float v = 0.5f;    // set other texture coordinate to middle
   

        output.uv.x = u;
        output.uv.y = v;
   
        output.diffuse = g_color;    
// save color
   
    
        
return output;
    }

兩點(diǎn)注解:

我們假設(shè)世界矩陣沒有執(zhí)行任何縮放。因?yàn)槿绻鼒?zhí)行,它就會(huì)弄亂乘以它的頂點(diǎn)的長度和方向。

我們總是設(shè)置v紋理坐標(biāo)為紋理的中點(diǎn)。這意味著我們僅使用紋理中一條單一的線,那就是說我們可以使用1D強(qiáng)度紋理來代替2D的那個(gè)紋理。不管怎樣,1D2D紋理都能工作。本例中,我們使用了2D紋理而不是1D紋理,這是沒有什么特別的原因的。

執(zhí)行程序:

      /**************************************************************************************************
      Demonstrates cartoon rendering using a vertex shader.  You will have to switch to 
      the REF device to run this sample if your hardware does not support shaders.  
      Or you can use software vertex processing: D3DCREATE_SOFTWARE_VERTEXPROCESSING. 
     **************************************************************************************************/

   
    #include "d3dUtility.h"
   
    #pragma warning(disable : 4100)
   
   
#define MESH_TEAPOT        0
   
#define MESH_SPHERE        1
   
#define MESH_TORUS        2
   
#define MESH_CYLINDER    3
   
   
const int WIDTH  = 640;
   
const int HEIGHT = 480;
   
    IDirect3DDevice9*        g_device;
    IDirect3DVertexShader9* g_vertex_shader;
    ID3DXConstantTable*        g_constant_table;
    IDirect3DTexture9*        g_shade_texture;
   
    ID3DXMesh*                g_meshes[4];
    D3DXMATRIX                g_world_matrices[4];
    D3DXVECTOR4                g_mesh_colors[4];
   
    D3DXMATRIX                g_proj_matrix;
   
    D3DXHANDLE                g_world_view_handle;
    D3DXHANDLE                g_world_view_proj_handle;
    D3DXHANDLE                g_color_handle;
    D3DXHANDLE                g_dir_to_light_handle;
   
   
    ////////////////////////////////////////////////////////////////////////////////////////////////////
   

   
bool setup()
    {    
        D3DXCreateTeapot(g_device, &g_meshes[MESH_TEAPOT], NULL);
        D3DXCreateSphere(g_device, 1.0f, 20, 20, &g_meshes[MESH_SPHERE], NULL);
        D3DXCreateTorus(g_device, 0.5f, 1.0f, 20, 20, &g_meshes[MESH_TORUS], NULL);
        D3DXCreateCylinder(g_device, 0.5f, 0.5f, 2.0f, 20, 20, &g_meshes[MESH_CYLINDER], NULL);
   
        D3DXMatrixTranslation(&g_world_matrices[MESH_TEAPOT],   0.0f,   2.0f, 0.0f);
        D3DXMatrixTranslation(&g_world_matrices[MESH_SPHERE],   0.0f,  -2.0f, 0.0f);
        D3DXMatrixTranslation(&g_world_matrices[MESH_TORUS],    -3.0f,  0.0f, 0.0f);
        D3DXMatrixTranslation(&g_world_matrices[MESH_CYLINDER],  3.0f,  0.0f, 0.0f);
   
        g_mesh_colors[MESH_TEAPOT]   = D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f);
        g_mesh_colors[MESH_SPHERE]   = D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f);
        g_mesh_colors[MESH_TORUS]    = D3DXVECTOR4(0.0f, 0.0f, 1.0f, 1.0f);
        g_mesh_colors[MESH_CYLINDER] = D3DXVECTOR4(1.0f, 1.0f, 0.0f, 1.0f);
   
        
// compile shader
   

        ID3DXBuffer*    shader_buffer;
        ID3DXBuffer*    error_buffer;
   
        HRESULT hr = D3DXCompileShaderFromFile("ToonShader.cxx", NULL, NULL, "main", "vs_1_1",
                                               D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY,
                                               &shader_buffer, &error_buffer, &g_constant_table);
   
        
// output any error messages
   
    if(error_buffer)
        {
            MessageBox(NULL, (
char*)error_buffer->GetBufferPointer(), "ERROR", MB_OK);
            safe_release<ID3DXBuffer*>(error_buffer);
        }
   
        
if(FAILED(hr))
        {
            MessageBox(NULL, "D3DXCreateEffectFromFile() - FAILED", "ERROR", MB_OK);
            
return false;
        }
   
        hr = g_device->CreateVertexShader((DWORD*) shader_buffer->GetBufferPointer(), &g_vertex_shader);
   
        
if(FAILED(hr))
        {
            MessageBox(NULL, "CreateVertexShader - FAILED", "ERROR", MB_OK);
            
return false;
        }
   
        safe_release<ID3DXBuffer*>(shader_buffer);
   
        
// load textures
   
        D3DXCreateTextureFromFile(g_device, "toonshade.bmp", &g_shade_texture);
   
        g_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
        g_device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
        g_device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);        
// disable mipmap
   
        // get handles
   
        g_world_view_handle            = g_constant_table->GetConstantByName(NULL, "g_world_view");
        g_world_view_proj_handle    = g_constant_table->GetConstantByName(NULL, "g_world_view_proj");
        g_color_handle                = g_constant_table->GetConstantByName(NULL, "g_color");        
        g_dir_to_light_handle        = g_constant_table->GetConstantByName(NULL, "g_dir_to_light");
   
        
// set shader constants
   
        D3DXVECTOR4 dir_to_light(-0.57f, 0.57f, -0.57f, 0.0f);
        g_constant_table->SetVector(g_device, g_dir_to_light_handle, &dir_to_light);
   
        g_constant_table->SetDefaults(g_device);
   
        
// set the projection matrix
   
        D3DXMatrixPerspectiveFovLH(&g_proj_matrix, D3DX_PI/4.0f, (float)WIDTH/HEIGHT, 1.0f, 1000.0f);
        
        
//g_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
   
    
        
return true;
    }
   
   
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
   

   
void cleanup()
    {    
        
for(int i = 0; i < 4; i++)
            safe_release<ID3DXMesh*>(g_meshes[i]);
   
        safe_release<IDirect3DTexture9*>(g_shade_texture);
        safe_release<IDirect3DVertexShader9*>(g_vertex_shader);
        safe_release<ID3DXConstantTable*>(g_constant_table);    
    }
   
   
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
   

   
bool display(float time_delta)
    {    
        
static float angle  = (3.0f * D3DX_PI) / 2.0f;
        
static float height = 5.0f;
   
        
if(GetAsyncKeyState(VK_LEFT) & 0x8000f)
            angle -= 0.5f * time_delta;
   
        
if(GetAsyncKeyState(VK_RIGHT) & 0x8000f)
            angle += 0.5f * time_delta;
   
        
if(GetAsyncKeyState(VK_UP) & 0x8000f)
            height += 5.0f * time_delta;
   
        
if(GetAsyncKeyState(VK_DOWN) & 0x8000f)
            height -= 5.0f * time_delta;
   
        D3DXVECTOR3 position(cosf(angle) * 7.0f, height, sinf(angle) * 7.0f);
        D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
        D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
   
        D3DXMATRIX view_matrix;
        D3DXMatrixLookAtLH(&view_matrix, &position, &target, &up);    
        
        
// render now
   

        g_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xFF333333, 1.0f, 0);
   
        g_device->BeginScene();
   
        g_device->SetVertexShader(g_vertex_shader);
        g_device->SetTexture(0, g_shade_texture);
   
        D3DXMATRIX world_view, world_view_proj;
   
        
for(int i = 0; i < 4; i++)
        {
            world_view        = g_world_matrices[i] * view_matrix;
            world_view_proj = g_world_matrices[i] * view_matrix * g_proj_matrix;
   
            g_constant_table->SetMatrix(g_device, g_world_view_handle,        &world_view);
            g_constant_table->SetMatrix(g_device, g_world_view_proj_handle, &world_view_proj);
   
            g_constant_table->SetVector(g_device, g_color_handle,            &g_mesh_colors[i]);
   
            g_meshes[i]->DrawSubset(0);
        }    
        
        g_device->EndScene();
   
        g_device->Present(NULL, NULL, NULL, NULL);
   
        
return true;
    }
   
   
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
   

    LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM word_param, LPARAM long_param)
    {
        
switch(msg)
        {
        
case WM_DESTROY:
            PostQuitMessage(0);
            
break;
   
        
case WM_KEYDOWN:
            
if(word_param == VK_ESCAPE)
                DestroyWindow(hwnd);
   
            
break;
        }
   
        
return DefWindowProc(hwnd, msg, word_param, long_param);
    }
   
   
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
   

   
int WINAPI WinMain(HINSTANCE inst, HINSTANCE, PSTR cmd_line, int cmd_show)
    {
        
if(! init_d3d(inst, WIDTH, HEIGHT, true, D3DDEVTYPE_HAL, &g_device))
        {
            MessageBox(NULL, "init_d3d() - failed.", 0, MB_OK);
            
return 0;
        }
   
        
if(! setup())
        {
            MessageBox(NULL, "Steup() - failed.", 0, MB_OK);
            
return 0;
        }
   
        enter_msg_loop(display);
   
        cleanup();
        g_device->Release();
   
        
return 0;
    }

運(yùn)行截圖:

 

下載源程序


posted on 2008-04-08 14:13 lovedday 閱讀(1681) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


公告

導(dǎo)航

統(tǒng)計(jì)

常用鏈接

隨筆分類(178)

3D游戲編程相關(guān)鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            一区二区三区日韩欧美精品| 久久久久久久久综合| 亚洲午夜精品17c| 亚洲欧美精品中文字幕在线| 亚洲欧美色一区| 亚洲无玛一区| 亚洲午夜av在线| 欧美在线免费一级片| 久久久女女女女999久久| 久久在线观看视频| 亚洲大片在线观看| 媚黑女一区二区| 亚洲人成人一区二区在线观看| 日韩一级大片在线| 香蕉成人啪国产精品视频综合网| 欧美伊人久久| 欧美大片免费久久精品三p | 亚洲三级色网| 亚洲午夜高清视频| 久久久久在线观看| 欧美日韩在线播放一区二区| 国产日韩欧美精品一区| 亚洲精品日本| 久久久久女教师免费一区| 亚洲国产高清一区| 欧美一区二区免费视频| 欧美精品一区在线播放| 好吊妞这里只有精品| 正在播放欧美视频| 久久精品视频在线看| 亚洲日本中文字幕区| 久久成人人人人精品欧| 欧美日韩一区二区视频在线观看| 精品成人国产在线观看男人呻吟| 亚洲一区二区在| 欧美激情在线狂野欧美精品| 亚洲一区在线视频| 欧美激情一区三区| 韩日午夜在线资源一区二区| 亚洲欧美日韩一区二区三区在线| 亚洲高清视频的网址| 久久精品91久久香蕉加勒比 | 国产欧美日韩在线视频| 亚洲久久在线| 免费在线观看成人av| 午夜精品视频在线观看| 欧美视频国产精品| 一区二区三区免费在线观看| 亚洲高清视频一区| 欧美va亚洲va日韩∨a综合色| 国产综合18久久久久久| 久久国产精品99精品国产| 亚洲天堂成人| 国产精品久久久久久久久搜平片 | 香蕉成人伊视频在线观看| 国产乱肥老妇国产一区二| 99精品热视频只有精品10| 欧美成人精品三级在线观看| 午夜精品久久久久影视| 国产精品久久久久91| 亚洲天堂视频在线观看| 亚洲精品之草原avav久久| 欧美激情在线播放| 99re在线精品| 99视频一区二区| 欧美日韩一区二区在线| 亚洲欧美日韩一区二区三区在线| 日韩亚洲国产欧美| 国产精品乱人伦一区二区| 欧美亚洲在线观看| 欧美呦呦网站| 亚洲电影在线看| 亚洲国语精品自产拍在线观看| 美女免费视频一区| 亚洲精品在线观看免费| 亚洲人成在线观看网站高清| 欧美日韩国产三区| 性欧美大战久久久久久久免费观看 | 欧美大片在线观看| 亚洲视频第一页| 亚洲欧美国产日韩中文字幕| 国内精品免费午夜毛片| 免费观看亚洲视频大全| 欧美国产丝袜视频| 亚洲免费在线观看| 久久精品日产第一区二区| 亚洲人成在线免费观看| 一区二区三区精密机械公司| 国产欧美一区视频| 亚洲丶国产丶欧美一区二区三区| 欧美日韩三级| 久久乐国产精品| 欧美二区不卡| 久久国产欧美精品| 免费人成精品欧美精品| 欧美亚洲在线视频| 欧美freesex交免费视频| 午夜视频在线观看一区二区三区| 久久久久久高潮国产精品视| 一区二区三区国产在线观看| 欧美亚洲免费电影| 亚洲少妇一区| 免费av成人在线| 欧美在线观看视频| 欧美日韩国产综合视频在线观看中文| 欧美一区三区二区在线观看| 欧美黄色精品| 另类人畜视频在线| 国产精品网站一区| 91久久夜色精品国产网站| 国产一区二区电影在线观看 | 免费美女久久99| 欧美激情性爽国产精品17p| 欧美在线观看视频一区二区| 欧美日韩视频免费播放| 欧美福利电影网| 国产一区二区三区在线观看免费| 亚洲精品久久久久久下一站| 激情成人中文字幕| 亚洲一区二区久久| 在线综合欧美| 欧美日韩视频一区二区| 欧美黄网免费在线观看| 激情视频一区二区| 欧美综合第一页| 欧美亚洲视频在线看网址| 欧美日韩成人网| 亚洲黄色在线观看| 亚洲黄色小视频| 麻豆精品传媒视频| 欧美大尺度在线观看| 亚洲第一中文字幕在线观看| 久久精品五月婷婷| 玖玖玖免费嫩草在线影院一区| 国产亚洲一区在线| 久久精品在线观看| 欧美aⅴ一区二区三区视频| 在线精品一区二区| 欧美高清视频一区二区三区在线观看| 欧美黑人一区二区三区| 亚洲精选成人| 欧美日韩mv| 亚洲一区亚洲| 久久在线免费观看| 亚洲精品国精品久久99热| 欧美大成色www永久网站婷| 亚洲精品免费在线观看| 一区二区三区日韩在线观看| 欧美日韩中字| 亚洲欧美视频在线观看| 久久亚洲精品一区二区| 亚洲国产精品久久人人爱蜜臀| 欧美电影在线观看| 一本久道久久综合中文字幕| 亚洲欧美国产日韩天堂区| 国产伦精品一区二区三区四区免费| 午夜视黄欧洲亚洲| 欧美va亚洲va日韩∨a综合色| 亚洲国产成人一区| 欧美日一区二区三区在线观看国产免| 亚洲一区日韩在线| 女同一区二区| 亚洲欧美综合网| 亚洲第一在线综合网站| 欧美三级视频在线| 久久久av网站| 亚洲裸体视频| 久久偷看各类wc女厕嘘嘘偷窃| 亚洲黄色影院| 国产欧美高清| 欧美精品日韩www.p站| 亚洲一二三四久久| 亚洲高清资源| 久久久久国产精品麻豆ai换脸| 亚洲三级视频在线观看| 国产日韩欧美高清| 欧美午夜片在线观看| 久久免费黄色| 亚洲欧美久久| 亚洲九九爱视频| 久久综合伊人77777| 久久国产精品久久w女人spa| 久久国产精品网站| 亚洲精品美女久久7777777| 欧美午夜宅男影院在线观看| 久久久噜噜噜久久人人看| 一区二区三区欧美日韩| 女同性一区二区三区人了人一| 午夜精品久久久久久久久久久| 亚洲日本va在线观看| 国产一区二区三区在线观看视频 | 亚洲国产精品va在线看黑人| 欧美午夜影院| 免费成人小视频| 欧美在线短视频| 亚洲一区二区三区乱码aⅴ| 亚洲欧洲一区二区三区久久| 麻豆精品视频在线观看视频| 欧美专区亚洲专区| 亚洲在线一区二区|