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

看图:

先说明:

光照 须要重写一个 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. SCOI2014总结

    似乎还没有写过SCOI的总结,今天补上,权当填坑. PS:CDQZ的看到了不要到处黑 SCOI-2014应该算是我的小高考,感觉拿住一本招的瓶颈就在这里.加之NOIp只有400分有点拖后腿,所以很早就 ...

  2. Highcharts Highstock 学习笔记 第一篇 Highcharts配置

    Highcharts是一款纯javascript编写的图表库,能够很简单便捷的在Web网站或Web应用中添加交互性的图表,Highcharts目前支持直线图.曲线图.面积图.柱状图.饼图.散点图等多达 ...

  3. 小小的IP,大大的耦合,你痛过吗?

    什么是耦合? 耦合,是架构中,本来不相干的代码.模块.服务.系统因为某些原因联系在一起,各自独立性差,影响则相互影响,变动则相互变动的一种架构状态. 感官上,怎么发现系统中的耦合? 作为技术人,每每在 ...

  4. SSH Secure Shell Client连接centos6.5时中文字乱码处理

    在学习Linux的过程中,最先碰到的是通过SSH终端连接时发现有乱码出现,使用这篇文章先从这里说起. 在 ssh , telnet 终端中文显示乱码解决办法#vim /etc/sysconfig/i1 ...

  5. JS——正则

    正则的声明: 1.构造函数:var 变量名= new RegExp(/表达式/); 2.直接量:var 变量名= /表达式/; test()方法: 1.正则对象方法,检测测试字符串是否符合该规则,返回 ...

  6. 解决richfaces自带的jquery

    项目里有个有史以来让人头疼的问题,就是前端的richfaces框架自带有jquery插件,而且好像总是在最后才加载,导致前面自己加载好的jquery版本的框架以及应用到jquery的其他前端框架生成的 ...

  7. linux中集群的免秘钥SSH直接登录

    这里以三台mysql的主从服务器为例:manage.master.slave1.slave2   给4个机器生成秘钥文件 以manage为例,执行命令,生成空字符串的秘钥(后面要使用公钥),命令是: ...

  8. windows 小知识---windows下生成公钥和私钥

    首先Windows操作系统需要安装git. 安装完成后,再到任意的文件夹内,点击右键.选择git bash here 打开之后,输入ssh-keygen,一路按enter键. 全部结束后,再到C:\U ...

  9. PyCharm社区版+Django搭建web开发环境

    PyCharm开源社区版不像商业版那样可以直接通过Django来创建项目,必须通过以下几个步骤进行: 1. 创建项目:在cmd命令行下输入:django-admin startproject Demo ...

  10. Scala 技术笔记之 Option Some None

    避免null使用 大多数语言都有一个特殊的关键字或者对象来表示一个对象引用的是“无”,在Java,它是null.在Java 里,null 是一个关键字,不是一个对象,所以对它调用任何方法都是非法的.但 ...