博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DirectX11 学习笔记8 - 最简单的光照
阅读量:6092 次
发布时间:2019-06-20

本文共 6820 字,大约阅读时间需要 22 分钟。

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

看图:

先说明:

光照 须要重写一个 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);}
你可能感兴趣的文章
SIP入门(二):建立SIPserver
查看>>
Servlet3.0的异步
查看>>
WebService连接postgresql( 失败尝试)
查看>>
从头认识java-13.11 对照数组与泛型容器,观察类型擦除给泛型容器带来什么问题?...
查看>>
Python-MacOSX下SIP引起的pip权限问题解决方案(非取消SIP机制)
查看>>
从MFQ方法到需求分析
查看>>
android.view.WindowManager$BadTokenException: Unable to add window
查看>>
HDU5012:Dice(bfs模板)
查看>>
iphone openssh
查看>>
Linux下MEncoder的编译
查看>>
spark高级排序彻底解秘
查看>>
ylbtech-LanguageSamples-PartialTypes(部分类型)
查看>>
福建省促进大数据发展:变分散式管理为统筹集中式管理
查看>>
开发环境、生产环境、测试环境的基本理解和区别
查看>>
tomcat多应用之间如何共享jar
查看>>
Flex前后台交互,service层调用后台服务的简单封装
查看>>
MySQL入门12-数据类型
查看>>
Windows Azure 保留已存在的虚拟网络外网IP(云服务)
查看>>
修改字符集
查看>>
HackTheGame 攻略 - 第四关
查看>>