zoukankan      html  css  js  c++  java
  • 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);
    }


  • 相关阅读:
    单调递增的数字
    合并K个升序链表
    ISO 8 自适应cell
    动态计算UITableViewCell高度
    APP上传
    多线程 GCD队列组
    多线程 线程之间的通信
    多线程 GCD
    多线程 线程同步问题
    多线程 线程的状态
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7122256.html
Copyright © 2011-2022 走看看