DirectX11 学习笔记8 - 最简单的光照
在上一个列子的基础上加了一个地面。这个地面是光照效果生成的。
看图:
先说明:
光照 须要重写一个 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 - 最简单的光照的更多相关文章
- Directx11学习笔记【一】 最简单的windows程序HelloWin
声明:本系列教程代码有部分来自dx11龙书及dx11游戏编程入门两本书,后面不再说明 首先,在vs2013中创建一个空的解决方案Dx11Demo,以后的工程都会放在这个解决方案下面.然后创建一个win ...
- Directx11学习笔记【二十二】 用高度图实现地形
本文由zhangbaochong原创,转载请注明出处http://www.cnblogs.com/zhangbaochong/p/5827714.html 在前面我们曾经实现过简单的地形(Direct ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第八章:光照
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第八章:光照 代码工程地址: https://github.com/j ...
- Directx11学习笔记【二十一】 封装键盘鼠标响应类
原文:Directx11学习笔记[二十一] 封装键盘鼠标响应类 摘要: 本文由zhangbaochong原创,转载请注明出处:http://www.cnblogs.com/zhangbaochong/ ...
- Directx11学习笔记【二】 将HelloWin封装成类
我们把上一个教程的代码封装到一个类中来方便以后的使用. 首先新建一个空工程叫做MyHelloWin,添加一个main.cpp文件,然后新建一个类叫做MyWindow,将于窗体有关的操作封装到里面 My ...
- Spring MVC 学习笔记10 —— 实现简单的用户管理(4.3)用户登录显示全局异常信息
</pre>Spring MVC 学习笔记10 -- 实现简单的用户管理(4.3)用户登录--显示全局异常信息<p></p><p></p>& ...
- Spring MVC 学习笔记9 —— 实现简单的用户管理(4)用户登录显示局部异常信息
Spring MVC 学习笔记9 -- 实现简单的用户管理(4.2)用户登录--显示局部异常信息 第二部分:显示局部异常信息,而不是500错误页 1. 写一个方法,把UserException传进来. ...
- Spring MVC 学习笔记8 —— 实现简单的用户管理(4)用户登录
Spring MVC 学习笔记8 -- 实现简单的用户管理(4)用户登录 增删改查,login 1. login.jsp,写在外面,及跟WEB-INF同一级目录,如:ls Webcontent; &g ...
- Directx11学习笔记【九】 3D渲染管线
原文:Directx11学习笔记[九] 3D渲染管线 原文地址:http://blog.csdn.net/bonchoix/article/details/8298116 3D图形学研究的基本内容,即 ...
随机推荐
- 题解报告:hdu 1232 畅通工程(并查集)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1232 Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了 ...
- 【转】Linux字符转换命令col
转自:http://www.cnblogs.com/ningvsban/p/3725464.html [root@www ~]# col [-xb]选项与参数:-x :将 tab 键转换成对等的空格键 ...
- Jquery和Ajax的关系!
Jquery是一种JavaScript框架,而Ajax(Asynchronous JavaScript and XML)是异步JavaScript和XML. Jquery是JavaScript的框架, ...
- C#学习-处理Excel
首先先了解下一个Excel文件的组成 1.一个Excel包含多个工作表(Sheet) 2.一个工作表(Sheet)包含多行(Row) 3.一行(Row)包含多个单元格(Cell) 如何判断一个单元 ...
- 3分钟看懂flex布局
首先要有个容器,并设置display:flex;display:-webkit-flex;该容器有以下六个属性: 1 2 3 4 5 6 7 8 9 10 11 12 flex-direction ( ...
- 解决sql server死锁
-- 查询死锁 select request_session_id spid,OBJECT_NAME(resource_associated_entity_id) tableName from sys ...
- JS高级——逻辑中断
1.表达式1||表达式2:表达式1为真,返回表达式1:表达式1为假,返回表达式2 2.表达式1&&表达2:表达式1为真,返回表达式2:表达式1为假,返回表达式1
- [Windows Server 2008] 查看ASP详细错误信息方法
★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com ★ 护卫神·V课堂是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:查看IIS下 ...
- Tomcat服务器安装与第一个jsp网页程序
1.安装tomcat服务器之前需要,先安装相应版本的jdk,个人理解Tomcat的大部分功能是使用了java的 jdk jar包的. jdk包下载方式网上可以查到 下载完后可以解压到一个指定目录,并在 ...
- JavaScript学习书签
JavaScript常用正则表达式 闭包 JavaScipt DOM 变量提升