【寒江雪】Direct3D11中的可编程光照

来源:互联网 发布:手机虚拟摇杆软件 编辑:程序博客网 时间:2024/04/30 16:31

  之前我们介绍过如何利用Effect来管理着色器的机制。而光照的实现也是在着色器中完成的。我们可以把光的渲染代码加到Effect文件中完成.
  对于光的类型,光源的类型,材质的一般属性,在我的另一篇学习笔记里有详细的阐述本着重复的事情只做一次的原则,我把链接贴出来:


http://blog.csdn.net/lkysyzxz/article/details/53559764

  这里我就简要介绍一下如何在Direct3D11中设置和使用光照
  在Direct3D11中,使用光照能让物体看起来真实感更佳。当光打到物体的表面,物体反射光的颜色进入人眼让物体看起来更具有真实感。而光照效果所呈现的最终颜色由物体的表面材质以及光的属性决定的.
  在可编程渲染管线中.就需要我们自己定义材质结构,光照结构.
  一个完整的材质结构定义如下:

struct Material//这是材质对各种光的反射率{    XMFLOAT4 ambient;//材质环境光    XMFLOAT4 diffuse;//材质漫反射光    XMFLOAT4 specular;//材质镜面光反射率    float    power;//镜面光反射系数};

  一个完整的光源结构定义如下:

//光源结构,这个结构包括了3中光源的所有属性//但不是每种属性都会用到,比如方向光就不会用到//光源位置以及衰减因子struct Light{    int type;   //光源类型,方向光:0,点光源:1,聚光灯:2    XMFLOAT4 position;  //光源位置    XMFLOAT4 direction; //方向向量    XMFLOAT4 ambient;   //环境光强度    XMFLOAT4 diffuse;   //漫反射光强度    XMFLOAT4 specular;  //镜面光强度    float attenuation0;//常量衰减因子    float attenuation1;//一次衰减因子    float attenuation2;//二次衰减因子    float alpha;    //聚光灯内锥角度    float beta;     //聚光灯外锥角度    float fallOff;  //聚光灯衰减系数,一般取值为1.0};//其中并不是所有的光源类型都会用到以上所有参数//例如方向光是没有位置的//所以存在一定的冗余,不过这一点冗余影响不大

设置光照的一般步骤

  概括地说,在可编程渲染管线模式下设置光照主要包括以下几个步骤:
* 设置材质参数
* 设置光照参数
* 设置视点位置
* 将材质参数和光照参数以及视点位置等相关参数设置到Effect文件中
* 利用特定的Technique对顶点着色
* 绘图得到最终效果

示例代码

LightScene.h

#pragma once#include"dxUtil.h"#include"Light.h"struct Vertex {    XMFLOAT3 Position;    XMFLOAT3 Norm;};class Scene;class Cube;class Cube {private:    Material           m_Mat;    ID3D11Buffer      *m_pVertexBuffer;//顶点缓存    UINT               m_uStrid;    UINT               m_uOffset;    ID3D11Buffer      *m_pIndexBuffer;//索引缓存    XMFLOAT4X4 m_world; //物体的位置public:    Cube()        : m_pVertexBuffer(NULL), m_pIndexBuffer(NULL)    {        XMStoreFloat4x4(&m_world, XMMatrixIdentity());    }    ID3D11Buffer ** GetVertexBuffer() {        return &m_pVertexBuffer;    }    ID3D11Buffer *GetIndexBuffer() {        return m_pIndexBuffer;    }    UINT GetStrid() {        return m_uStrid;    }    UINT GetOffset() {        return m_uOffset;    }    Material GetMaterial(){        return m_Mat;    }    XMMATRIX GetWorldPosition() {        return XMLoadFloat4x4(&m_world);    }    HRESULT Init(DirectSystem* d3dSys) {        HRESULT hr;        Vertex vertices[] = {            { XMFLOAT3(1,1,1),XMFLOAT3(1,1,1) },            { XMFLOAT3(-1,1,1),XMFLOAT3(-1,1,1) },            { XMFLOAT3(-1,-1,1),XMFLOAT3(-1,-1,1) },            { XMFLOAT3(1,-1,1),XMFLOAT3(1,-1,1) },            { XMFLOAT3(1,1,-1),XMFLOAT3(1,1,-1) },            { XMFLOAT3(-1,1,-1),XMFLOAT3(-1,1,-1) },            { XMFLOAT3(-1,-1,-1),XMFLOAT3(-1,-1,-1) },            { XMFLOAT3(1,-1,-1),XMFLOAT3(1,-1,-1) },        };        WORD indexs[] =        {            0,1,2,            0,2,3,            4,6,5,            4,7,6,            0,4,5,            0,5,1,            3,2,6,            3,6,7,            5,6,2,            5,2,1,            3,4,0,            3,7,4        };        D3D11_BUFFER_DESC vertexBuffer;        ::ZeroMemory(&vertexBuffer, sizeof(vertexBuffer));        vertexBuffer.BindFlags = D3D11_BIND_VERTEX_BUFFER;        vertexBuffer.ByteWidth = sizeof(Vertex) * ARRAYSIZE(vertices);        vertexBuffer.CPUAccessFlags = 0;        vertexBuffer.Usage = D3D11_USAGE_DEFAULT;        D3D11_SUBRESOURCE_DATA initVertexData;        ::ZeroMemory(&initVertexData, sizeof(initVertexData));        initVertexData.pSysMem = vertices;        hr=d3dSys->D3DDevice()->CreateBuffer(&vertexBuffer, &initVertexData,&m_pVertexBuffer);        if (FAILED(hr))        {            return hr;        }        m_uStrid = sizeof(Vertex);        m_uOffset = 0;        D3D11_BUFFER_DESC indexBuffer;        ::ZeroMemory(&indexBuffer, sizeof(indexBuffer));        indexBuffer.BindFlags = D3D11_BIND_INDEX_BUFFER;        indexBuffer.ByteWidth = sizeof(WORD)*ARRAYSIZE(indexs);        indexBuffer.Usage = D3D11_USAGE_DEFAULT;        D3D11_SUBRESOURCE_DATA initIndexData;        ::ZeroMemory(&initIndexData, sizeof(initIndexData));        initIndexData.pSysMem = indexs;        hr=d3dSys->D3DDevice()->CreateBuffer(&indexBuffer, &initIndexData, &m_pIndexBuffer);        if (FAILED(hr)) {            return hr;        }        m_Mat.ambient = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);        m_Mat.diffuse = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);        m_Mat.specular = XMFLOAT4(1.0f, 1.0f, 1.0f,1.0f);        m_Mat.power = 5.0f;        return S_OK;    }    HRESULT SetCubeParm(DirectSystem *d3dSys,ID3DX11Effect *effect) {        d3dSys->D3DDeviceContext()->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &m_uStrid, &m_uOffset);        d3dSys->D3DDeviceContext()->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0);        d3dSys->D3DDeviceContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);        effect->GetVariableByName("World")->AsMatrix()->SetMatrix((float*)&m_world);        effect->GetVariableByName("MatAmbient")->AsVector()->SetFloatVector((float*)&m_Mat.ambient);        effect->GetVariableByName("MatDiffuse")->AsVector()->SetFloatVector((float*)&m_Mat.diffuse);        effect->GetVariableByName("MatSpecular")->AsVector()->SetFloatVector((float*)&m_Mat.specular);        effect->GetVariableByName("MatPower")->AsScalar()->SetFloat(m_Mat.power);        return S_OK;    }    VOID Update(float deltaTime) {        static float angle = 0;        angle += deltaTime;        if (angle > 6.28f)            angle = 0.0f;        XMMATRIX world;        world=XMLoadFloat4x4(&m_world);        world=XMMatrixRotationY(angle);        XMStoreFloat4x4(&m_world, world);    }    ~Cube() {        SAFE_RELEASE(m_pVertexBuffer);        SAFE_RELEASE(m_pIndexBuffer);    }};class Scene {private:    ID3DX11Effect     *m_pEffect;    ID3DX11EffectTechnique *m_pTechnique;    ID3D11InputLayout *m_pInputLayout;  //输入布局    Cube *m_pCube;    Light m_PointLight;public:    Scene()        :m_pEffect(NULL),m_pTechnique(NULL),m_pInputLayout(NULL),m_pCube(NULL)    {    }    HRESULT Draw(DirectSystem *d3dSys) {        XMMATRIX view;        XMMATRIX projection;        XMVECTOR eyePosition;        view  = d3dSys->GetViewMatrix();        projection = d3dSys->GetProjectionMatrix();        eyePosition = d3dSys->GetEyePosition();        m_pCube->SetCubeParm(d3dSys,m_pEffect);        m_pEffect->GetVariableByName("View")->AsMatrix()->SetMatrix((float*)&view);        m_pEffect->GetVariableByName("Projection")->AsMatrix()->SetMatrix((float*)&projection);        m_pEffect->GetVariableByName("EyePosition")->AsVector()->SetFloatVector((float*)&eyePosition);        m_pEffect->GetVariableByName("type")->AsScalar()->SetInt(m_PointLight.type);        m_pEffect->GetVariableByName("LightPosition")->AsVector()->SetFloatVector((float*)&m_PointLight.position);        m_pEffect->GetVariableByName("LightAmbient")->AsVector()->SetFloatVector((float*)&m_PointLight.ambient);        m_pEffect->GetVariableByName("LightDiffuse")->AsVector()->SetFloatVector((float*)&m_PointLight.diffuse);        m_pEffect->GetVariableByName("LightSpecular")->AsVector()->SetFloatVector((float*)&m_PointLight.specular);        m_pEffect->GetVariableByName("LightAtt0")->AsScalar()->SetFloat(m_PointLight.attenuation0);        m_pEffect->GetVariableByName("LightAtt1")->AsScalar()->SetFloat(m_PointLight.attenuation1);        m_pEffect->GetVariableByName("LightAtt2")->AsScalar()->SetFloat(m_PointLight.attenuation2);        d3dSys->D3DDeviceContext()->IASetInputLayout(m_pInputLayout);        m_pTechnique->GetPassByIndex(0)->Apply(0, d3dSys->D3DDeviceContext());        d3dSys->D3DDeviceContext()->DrawIndexed(36, 0, 0);        return S_OK;    }    VOID Update(float deltaTime) {        m_pCube->Update(deltaTime);    }    HRESULT Init(DirectSystem *d3dSys) {        HRESULT hr;        ID3DBlob *effectBlob;        hr=D3DX11CompileFromFile(L"LightShader.fx", NULL, NULL,            NULL, "fx_5_0", NULL, 0, NULL, &effectBlob, NULL, NULL);        if (FAILED(hr)) {            return hr;        }        hr=D3DX11CreateEffectFromMemory(effectBlob->GetBufferPointer(), effectBlob->GetBufferSize(),            0, d3dSys->D3DDevice(), &m_pEffect, NULL);        if (FAILED(hr)) {            return hr;        }        m_pTechnique = m_pEffect->GetTechniqueByName("T0");        D3DX11_PASS_DESC passDesc;        m_pTechnique->GetPassByIndex(0)->GetDesc(&passDesc);        D3D11_INPUT_ELEMENT_DESC inputDesc[] = {            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0 },            { "NORMAL",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }        };        UINT inputDescNum = ARRAYSIZE(inputDesc);        hr = d3dSys->D3DDevice()->CreateInputLayout(inputDesc, inputDescNum,            passDesc.pIAInputSignature, passDesc.IAInputSignatureSize, &m_pInputLayout);        if (FAILED(hr)) {            return hr;        }        m_pCube = new Cube();        m_pCube->Init(d3dSys);        m_PointLight.type = 1;        m_PointLight.position = XMFLOAT4(-4.0f, 4.0f, -4.0f, 1.0f);        m_PointLight.diffuse = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);        m_PointLight.ambient = XMFLOAT4(0.3f, 0.2f, 0.1f, 1.0f);        m_PointLight.specular = XMFLOAT4(0.5f, 0.5f, 0.9f, 1.0f);        m_PointLight.attenuation0 = 0;        m_PointLight.attenuation1 = 0.1f;        m_PointLight.attenuation2 = 0;        m_pTechnique = m_pEffect->GetTechniqueByName("T_PointLight");    }    ~Scene() {        delete m_pCube;        SAFE_RELEASE(m_pInputLayout);        SAFE_RELEASE(m_pTechnique);        SAFE_RELEASE(m_pEffect);    }};


Copyright© by 寒江雪
Date:2016.12.31

0 0
原创粉丝点击