在上一个列子的基础上加了一个地面。这个地面是光照效果生成的。

看图:

先说明:

光照 须要重写一个 lightshader  就是光照的渲染器

// Define the input layout
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};

你会发现之前的第二行是Color而不是如今的Normal 。 由于光照的颜色是有外界 环境光 透射光 漫反射光 形成的。

这些光的计算所有写在一个效果文件lightShader.fx里面

//--------------------------------------------------------------------------------------
// Constant Buffer Variables
//--------------------------------------------------------------------------------------
cbuffer ConstantBuffer
{
matrix World;
matrix View;
matrix Projection;
};
cbuffer LightBuffer
{
float3 cameraPosition;
float padding;
};
//--------------------------------------------------------------------------------------
struct VS_INPUT
{
float4 Pos : POSITION;
float3 Normal : NORMAL;
};
struct VS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 Color : COLOR;
}; //--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
VS_OUTPUT VS( VS_INPUT input )
{
VS_OUTPUT output = (VS_OUTPUT)0;
float4 worldPosition;
// 改变顶点为四个分量其次坐标.
input.Pos.w = 1.0f;
output.Pos = mul( input.Pos, World );
output.Pos = mul( output.Pos, View );
output.Pos = mul( output.Pos, Projection );
// 世界坐标系中的顶点法向.
float3 N = mul(input.Normal, (float3x3)World);
N = normalize(N);
//世界坐标系顶点位置
float3 P = output.Pos.xyz; //自发射颜色
float3 emissive = float3(0.0, 0.0, 0.0); //计算环境光
float3 ambient = float3(0.3, 0.3, 0.3); //计算漫反射光
float3 L = normalize(float3(-1.0, -1.0, 1.0));
float diffuseLight = max(dot(N, L), 0);
float3 diffuse = diffuseLight; //计算高光
float3 V = normalize(cameraPosition - P);
float3 H = normalize(L + V);
float specularLight = pow(max(dot(N, H), 0), 5.0); if (diffuseLight <= 0)
specularLight = 0;
float3 specular = specularLight; output.Color.xyz = emissive + ambient + diffuse + specular;
// float3 tt = float3(1.0, 0.0, 0.0);
// output.color.xyz = float3(1.0, 0.0, 0.0);
output.Color.w = 1.0f; return output;
} //--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS( VS_OUTPUT input ) : SV_Target
{
return input.Color;
}

主要就是顶点输入进行复杂的光照计算,龙书上有。还多了一个缓冲区

cbuffer LightBuffer
{
float3 cameraPosition;
float padding;
};

眼下仅仅存了光照的颜色 主要 要为4的倍数 对齐float地址

//create the light buffer
ZeroMemory( &bd, sizeof(bd) );
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(LightBuffer);
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = 0;
hr = device->CreateBuffer( &bd, NULL, &m_lightmaterialBuffer );
if( FAILED( hr ) )
return hr;

光照渲染文件中面的缓冲区创建

//
// Update variables
//
ConstantBuffer cb;
cb.mWorld = XMMatrixTranspose( worldMatrix);
cb.mView = XMMatrixTranspose( viewMatrix );
cb.mProjection = XMMatrixTranspose( projectionMatrix );
deviceContext->UpdateSubresource( m_matrixBuffer, 0, NULL, &cb, 0, 0 );
deviceContext->VSSetConstantBuffers( 0, 1, &m_matrixBuffer );
LightBuffer lb;
lb.cameraPosition=cameraPos;
deviceContext->UpdateSubresource( m_lightmaterialBuffer, 0, NULL, &lb, 0, 0 );
deviceContext->VSSetConstantBuffers( 1, 1, &m_matrixBuffer );

比曾经多了一个缓冲区更新。

有了光照效果文件  光照渲染器 还差一个承载物

这里是一个四边形,作为大地吧

PlaneModel.h

#pragma  once
#include "XComm.h"
class PlaneModel
{
protected:
struct SimpleVertexN
{
XMFLOAT3 Pos;
XMFLOAT3 Normal;
};
public://顶点缓冲和顶点索引缓冲
ID3D11Buffer *m_vertexBuffer, *m_indexBuffer;
int m_vertexCount, m_indexCount;
public:
PlaneModel():m_vertexCount(0),m_indexCount(0){};
bool init(ID3D11Device*);
void close();
void render(ID3D11DeviceContext*);
};

基本跟之前立方体的方法是一摸一样的 仅仅只是把color颜色换成了法向normal

PlaneModel.cpp

#include "PlaneModel.h"
bool PlaneModel::init(ID3D11Device* device)
{
SimpleVertexN* vertices;
unsigned long* indices;
D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc;
D3D11_SUBRESOURCE_DATA vertexData, indexData;
HRESULT result; //首先,我们创建2个暂时缓冲存放顶点和索引数据,以便后面使用。. // 设置顶点缓冲大小为4,一个平面.
m_vertexCount = 4; // 设置索引缓冲大小.,两个三角形
m_indexCount = 6; // 创建顶点暂时缓冲.
vertices = new SimpleVertexN[m_vertexCount];
if(!vertices)
{
return false;
} // 创建索引缓冲.
indices = new unsigned long[m_indexCount];
if(!indices)
{
return false;
}
//创建顺时针方向的三角形,左手规则
// 设置顶点数据.
vertices[0].Pos = XMFLOAT3(-50.0f, -3.0f, -50.0f);
vertices[0].Normal = XMFLOAT3(0.0f, 1.0f, 0.0f); vertices[1].Pos = XMFLOAT3(-50.0f,-3.0f, 50.0f);
vertices[1].Normal = XMFLOAT3(0.0f, 1.0f, 0.0f); vertices[2].Pos = XMFLOAT3(50.0f, -3.0f, 50.0f);
vertices[2].Normal= XMFLOAT3(0.0f, 1.0f, 0.0f); vertices[3].Pos = XMFLOAT3(50.0f, -3.0f, -50.0f);
vertices[3].Normal = XMFLOAT3(0.0f, 1.0f, 0.0f); // 设置索引缓冲数据.
indices[0] = 0; // 前面
indices[1] = 1;
indices[2] = 2;
indices[3] = 0;
indices[4] = 2;
indices[5] = 3; // 设置顶点缓冲描写叙述
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.ByteWidth = sizeof(SimpleVertexN) * m_vertexCount;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;
vertexBufferDesc.StructureByteStride = 0; // 指向保存顶点数据的暂时缓冲.
vertexData.pSysMem = vertices;
vertexData.SysMemPitch = 0;
vertexData.SysMemSlicePitch = 0; // 创建顶点缓冲.
result = device->CreateBuffer(&vertexBufferDesc, &vertexData, &m_vertexBuffer);
if(FAILED(result))
{
HR(result);
return false;
} // 设置索引缓冲描写叙述.
indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
indexBufferDesc.ByteWidth = sizeof(unsigned long) * m_indexCount;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDesc.CPUAccessFlags = 0;
indexBufferDesc.MiscFlags = 0;
indexBufferDesc.StructureByteStride = 0; // 指向存暂时索引缓冲.
indexData.pSysMem = indices;
indexData.SysMemPitch = 0;
indexData.SysMemSlicePitch = 0; // 创建索引缓冲.
result = device->CreateBuffer(&indexBufferDesc, &indexData, &m_indexBuffer);
if(FAILED(result))
{
HR(result);
return false;
} // 释放暂时缓冲.
delete [] vertices;
vertices = 0; delete [] indices;
indices = 0;
}
void PlaneModel::close()
{
// 释放顶点缓冲.
if(m_indexBuffer)
{
m_indexBuffer->Release();
m_indexBuffer = 0;
} // 释放索引缓冲
if(m_vertexBuffer)
{
m_vertexBuffer->Release();
m_vertexBuffer = 0;
}
}
void PlaneModel::render(ID3D11DeviceContext* deviceContext)
{
unsigned int stride;
unsigned int offset; // 设置顶点缓冲跨度和偏移.
stride = sizeof(SimpleVertexN);
offset = 0; //在input assemberl阶段绑定顶点缓冲,以便可以被渲染
deviceContext->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset); //在input assemberl阶段绑定索引缓冲。以便可以被渲染
deviceContext->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0); // 设置体元语义,渲染三角形列表.
//注意这里和XModel不一样
deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
}

DirectX11 学习笔记8 - 最简单的光照的更多相关文章

  1. Directx11学习笔记【一】 最简单的windows程序HelloWin

    声明:本系列教程代码有部分来自dx11龙书及dx11游戏编程入门两本书,后面不再说明 首先,在vs2013中创建一个空的解决方案Dx11Demo,以后的工程都会放在这个解决方案下面.然后创建一个win ...

  2. Directx11学习笔记【二十二】 用高度图实现地形

    本文由zhangbaochong原创,转载请注明出处http://www.cnblogs.com/zhangbaochong/p/5827714.html 在前面我们曾经实现过简单的地形(Direct ...

  3. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第八章:光照

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第八章:光照 代码工程地址: https://github.com/j ...

  4. Directx11学习笔记【二十一】 封装键盘鼠标响应类

    原文:Directx11学习笔记[二十一] 封装键盘鼠标响应类 摘要: 本文由zhangbaochong原创,转载请注明出处:http://www.cnblogs.com/zhangbaochong/ ...

  5. Directx11学习笔记【二】 将HelloWin封装成类

    我们把上一个教程的代码封装到一个类中来方便以后的使用. 首先新建一个空工程叫做MyHelloWin,添加一个main.cpp文件,然后新建一个类叫做MyWindow,将于窗体有关的操作封装到里面 My ...

  6. Spring MVC 学习笔记10 —— 实现简单的用户管理(4.3)用户登录显示全局异常信息

    </pre>Spring MVC 学习笔记10 -- 实现简单的用户管理(4.3)用户登录--显示全局异常信息<p></p><p></p>& ...

  7. Spring MVC 学习笔记9 —— 实现简单的用户管理(4)用户登录显示局部异常信息

    Spring MVC 学习笔记9 -- 实现简单的用户管理(4.2)用户登录--显示局部异常信息 第二部分:显示局部异常信息,而不是500错误页 1. 写一个方法,把UserException传进来. ...

  8. Spring MVC 学习笔记8 —— 实现简单的用户管理(4)用户登录

    Spring MVC 学习笔记8 -- 实现简单的用户管理(4)用户登录 增删改查,login 1. login.jsp,写在外面,及跟WEB-INF同一级目录,如:ls Webcontent; &g ...

  9. Directx11学习笔记【九】 3D渲染管线

    原文:Directx11学习笔记[九] 3D渲染管线 原文地址:http://blog.csdn.net/bonchoix/article/details/8298116 3D图形学研究的基本内容,即 ...

随机推荐

  1. 【BZOJ2565】最长双回文串 (Manacher算法)

    题目: BZOJ2565 分析: 首先看到回文串,肯定能想到Manacher算法.下文中字符串\(s\)是输入的字符串\(str\)在Manacher算法中添加了字符'#'后的字符串 (构造方式如下) ...

  2. android sqlite中判断某个表是否存在

    <span style="font-size:18px;">sqlite 中判断某个表是否存在的方法,贴出来供大家参考 /** * 判断某张表是否存在 * @param ...

  3. Mac使用bootcamp安装win8.1出现网卡驱动没有安装问题

    问题:没有网络连接 原因:在bootcamp烧的u盘里面其实附带了驱动,只是没有自动安装 解决:D:\BootCamp\Drivers\Broadcom\BroadcomWirelessWin8x64 ...

  4. netty学习:UDP服务器与Spring整合

    最近接到一个关于写UDP服务器的任务,然后去netty官网下载了netty的jar包(netty-4.0.49.Final.tar.bz2),解压后,可以看到上面有不少example,找到其中的关于U ...

  5. DeltaFish 小组成员及个人博客地址

    艾寅中  http://www.cnblogs.com/aiyz 陈志锴  http://www.cnblogs.com/chenzhikai 李   鑫  http://www.cnblogs.co ...

  6. 从ABC到流利口语-unit01

    Unit 1 Introduction1 Good evening,everyone.It's a pleasure to you all. My name is Wang Dong.I'M from ...

  7. CAD向控件注册一个命令(com接口VB语言)

    主要用到函数说明: MxDrawXCustomFunction::Mx_RegistUserCustomCommand 向控件注册一个命令,用户在命令行输入命令名这个字符串,就会触发执行命令事件 命令 ...

  8. CAD从线型文件加载线型记录(com接口)

    主要用到函数说明: _DMxDrawX::LoadLinetypeFromFile 从线型文件加载线型记录,详细说明如下: 参数 说明 BSTR pszLinetypeFile 线型文件名,支持htt ...

  9. P1638 逛画展

    题目描述 博览馆正在展出由世上最佳的 M 位画家所画的图画. wangjy想到博览馆去看这几位大师的作品. 可是,那里的博览馆有一个很奇怪的规定,就是在购买门票时必须说明两个数字, a和b,代表他要看 ...

  10. C语言实现截屏

    实现手机控制电脑执行部分功能需要获取桌面状态,在网上找的一段截屏代码 /** * GDI 截屏函数 * 参数 hwnd 要截屏的窗口句柄 * 参数 dirPath 截图存放目录 * 参数 filena ...