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图形学研究的基本内容,即 ...
随机推荐
- html基础代码演示2
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...
- Linux命令(002) -- free
一.准备知识 Linux和Windows系统在内存管理机制方面有很大的不同.在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的 ...
- [转]使用ThinkPHP框架快速开发网站(多图)
本文转自:http://blog.csdn.net/ruby97/article/details/7574851 这一周一直忙于做实验室的网站,基本功能算是完成了.比较有收获的是大概了解了ThinkP ...
- JS——放大镜
放大镜: 1.比例系数要恒定:在系数为4的情况下,若原图是820*512,那么小图必须是205*128,放大镜若是50,原图显示区域必须200 2.计算鼠标在小图中的坐标 3.放大镜需要在鼠标中间位置 ...
- java攻城师之路--复习java web之request_respone
Servlet技术 两条主线1.HTTP协议 2.Servlet生命周期 init() 方法中参数 ServletConfig 对象使用通过ServletConfig 获得 ServletContex ...
- [Windows Server 2012] Filezilla安装方法
★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com ★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:FileZ ...
- Git 分支创建
分支策略:git上始终保持两个分支,master分支与develop分支.master分支主要用于发布时使用,而develop分支主要用于开发使用. 创建master的分支developgit che ...
- CaffeMFC:caffe.pb.h(2525): error C2059: syntax error : 'constant'
下边的语句会报 syntax error : 'constant'. static const DimCheckMode STRICT = V1LayerParameter_DimCheckMode_ ...
- (转)OGNL与值栈
http://blog.csdn.net/yerenyuan_pku/article/details/67709693 OGNL的概述 什么是OGNL 据度娘所说: OGNL是Object-Graph ...
- PHP 之中文转为拼音
/** * Created by PhpStorm. * User: Administrator * Date: 2019/1/2 0002 * Time: 下午 1:01 */ class PinY ...