Vulkan开发实战详解 学习笔记 - 点法向量和面法向量

点法向量和面法向量

是基于球面开发的,球面属于连续、平滑的曲面,因此面上的每个顶点都有确定的法向量。但现实世界中的物体表面并不都是连续、平滑的,此时对于面上的某些点的法向量计算就不那么直观了.

从图5-18中可以看出,顶点A位于长方体左、上、前3个面的交界处,此处是不光滑的。这种情况下顶点A的法向量有两种处理策略,具体情况如下。某些点的法向量计算就不那么直观了.

在这里插入图片描述

在顶点A的位置放置3个不同的顶点,并认为每个顶点仅属于一个面,各个顶点的法向量即为其所属面的法向量。这种策略就是面法向量的策略,比较适合棱角分明的物体。

顶点A的位置仅放置一个顶点,其法向量取其所属所有面法向量的平均值。这种策略就是点法向量策略,比较适合用于由多个小平面搭建平滑曲面的情况。角分明的物体。

首先给出的是采用面法向量策略的案例,中初始化立方体顶点及法向量数据的genData方法,其具体代码如下

CubeData.cpp

#include "CubeData.h"
#include <vector>
#include <math.h>
#include <string.h>float* CubeData::vdata;
int CubeData::dataByteCount;
int CubeData::vCount;
void  CubeData::genData()
{const float rect = 1.0f;//立方体的边长std::vector<float> alVertix;//存放顶点坐标的vectorstd::vector<float> alNormal;// 存放法向量的vectoralVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(rect);//1alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(rect);//2alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(rect);//3alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(rect);//1alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(rect);//3alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(rect);// 2'//后面alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(-rect);//1alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(-rect);//2alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//3alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(-rect);//1alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//3alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(-rect);// 2'//左面alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//3alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(-rect);//2alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(rect);//1alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(rect);//3alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//2alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(rect);//1//右面alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//3alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(-rect);//2alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(rect);//1alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(rect);//3alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//2alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(rect);//1//上面alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(-rect);//3alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(-rect);//2alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(rect);//1alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(rect);//3alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(-rect);//2alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(rect);//1//下面alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//3alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//2alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(rect);//1alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(rect);//3alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//2alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(rect);//1//前面alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(1);//后面alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(-1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(-1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(-1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(-1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(-1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(-1);//左面alNormal.push_back(-1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(-1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(-1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(-1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(-1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(-1); alNormal.push_back(0); alNormal.push_back(0);//右面alNormal.push_back(1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(1); alNormal.push_back(0); alNormal.push_back(0);//上面alNormal.push_back(0); alNormal.push_back(1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(1); alNormal.push_back(0);//下面alNormal.push_back(0); alNormal.push_back(-1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(-1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(-1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(-1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(-1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(-1); alNormal.push_back(0);vCount = alVertix.size() / 3;// 顶点的数量为坐标值数量的1/3,因为一个顶点有3个坐标dataByteCount = alVertix.size() * 2 * sizeof(float);//顶点和法向量数据的总字节数vdata = new float[alVertix.size() * 2];//存放顶点坐标和法向量数据的数组int index = 0;//辅助数组索引for (int i = 0; i<vCount; i++){vdata[index++] = alVertix[i * 3 + 0]; //保存顶点坐标X 分量vdata[index++] = alVertix[i * 3 + 1]; //保存顶点坐标Y 分量vdata[index++] = alVertix[i * 3 + 2]; //保存顶点坐标Z 分量vdata[index++] = alNormal[i * 3 + 0]; //保存顶点法向量X 分量vdata[index++] = alNormal[i * 3 + 1]; //保存顶点法向量Y 分量vdata[index++] = alNormal[i * 3 + 2]; //保存顶点法向量Z 分量}
}

CubeData.cpp

#include "CubeData.h"
#include <vector>
#include <math.h>
#include <string.h>float* CubeData::vdata;
int CubeData::dataByteCount;
int CubeData::vCount;
void  CubeData::genData()
{const float rect = 1.0f;//立方体的边长std::vector<float> alVertix;//存放顶点坐标的vectorstd::vector<float> alNormal;// 存放法向量的vectoralVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(rect);//1alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(rect);//2alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(rect);//3alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(rect);//1alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(rect);//3alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(rect);// 2'//后面alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(-rect);//1alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(-rect);//2alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//3alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(-rect);//1alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//3alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(-rect);// 2'//左面alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//3alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(-rect);//2alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(rect);//1alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(rect);//3alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//2alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(rect);//1//右面alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//3alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(-rect);//2alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(rect);//1alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(rect);//3alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//2alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(rect);//1//上面alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(-rect);//3alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(-rect);//2alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(rect);//1alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(rect);//3alVertix.push_back(-rect); alVertix.push_back(rect); alVertix.push_back(-rect);//2alVertix.push_back(rect); alVertix.push_back(rect); alVertix.push_back(rect);//1//下面alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//3alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//2alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(rect);//1alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(rect);//3alVertix.push_back(-rect); alVertix.push_back(-rect); alVertix.push_back(-rect);//2alVertix.push_back(rect); alVertix.push_back(-rect); alVertix.push_back(rect);//1//前面alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(1);//后面alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(-1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(-1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(-1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(-1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(-1);alNormal.push_back(0); alNormal.push_back(0); alNormal.push_back(-1);//左面alNormal.push_back(-1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(-1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(-1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(-1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(-1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(-1); alNormal.push_back(0); alNormal.push_back(0);//右面alNormal.push_back(1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(1); alNormal.push_back(0); alNormal.push_back(0);alNormal.push_back(1); alNormal.push_back(0); alNormal.push_back(0);//上面alNormal.push_back(0); alNormal.push_back(1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(1); alNormal.push_back(0);//下面alNormal.push_back(0); alNormal.push_back(-1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(-1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(-1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(-1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(-1); alNormal.push_back(0);alNormal.push_back(0); alNormal.push_back(-1); alNormal.push_back(0);vCount = alVertix.size() / 3;// 顶点的数量为坐标值数量的1/3,因为一个顶点有3个坐标dataByteCount = alVertix.size() * 2 * sizeof(float);//顶点和法向量数据的总字节数vdata = new float[alVertix.size() * 2];//存放顶点坐标和法向量数据的数组int index = 0;//辅助数组索引for (int i = 0; i<vCount; i++){vdata[index++] = alVertix[i * 3 + 0]; //保存顶点坐标X 分量vdata[index++] = alVertix[i * 3 + 1]; //保存顶点坐标Y 分量vdata[index++] = alVertix[i * 3 + 2]; //保存顶点坐标Z 分量vdata[index++] = alNormal[i * 3 + 0]; //保存顶点法向量X 分量vdata[index++] = alNormal[i * 3 + 1]; //保存顶点法向量Y 分量vdata[index++] = alNormal[i * 3 + 2]; //保存顶点法向量Z 分量}
}

中原始情况下将立方体的几何中心放在了坐标原点,同时立方体的各条棱都与坐标轴平行,故每个顶点的平均法向量就没有必要真正进行求和再平均的计算了,直接采用各个顶点的x、y、z坐标值代替即可。但开发中点平均法向量的计算并不总是像本章的案例一样可以进行简化.

在这里插入图片描述

在这里插入图片描述

光照的每顶点计算与每片元计算

在顶点着色器中进行光照计算的。在顶点着色器中对每个顶点进行光照计算后得到顶点的最终光照强度,再由管线插值后传入片元着色器以计算片元的颜色,这样一方面效率比较高,另一方面产生的光照效果也不错。

但由于这种计算方式插值的是基于顶点计算后的光照强度,因此并不适用于所有的场景。若光源离被照射物体各个三角形面的距离与三角形的尺寸接近时,这样的计算策略形成的视觉效果就可能很不真实了. 每顶点计算光照的方式在图形学中称之为Gouraud着色,每片元计算光照的方式在图形学中称之为Phong着色。

FlatData.h

#ifndef VULKANEXBASE_BALLDATA_H
#define VULKANEXBASE_BALLDATA_H //防止重复引用
class FlatData {
public:static float* vdata; //数据数组首地址指针static int dataByteCount; //数据所占总字节数static int vCount; //顶点数量static void genData(); //生成顶点数据的方法
};
#endif

FlatData.cpp

#include "FlatData.h"
#include <vector>
#include <math.h>
#include <string.h>
float* FlatData::vdata; //数据数组首地址指针
int FlatData::dataByteCount; //数据所占总字节数
int FlatData::vCount; //顶点数量
void FlatData::genData() { //顶点数据生成方法vCount = 6; //顶点数量为6dataByteCount = vCount * 6 * sizeof(float); //数据所占内存总字节数vdata = new float[vCount * 6]{ //顶点数据数组3, 2, 0, 0, 0, 1, -3, 2, 0, 0, 0, 1, //每个顶点6 个数据-3, -2, 0, 0, 0, 1, 3, -2, 0, 0, 0, 1, //前3 个是顶点位置坐标XYZ 分量3, 2, 0, 0, 0, 1, -3, -2, 0, 0, 0, 1 }; //后3 个是顶点法向量XYZ 分量
}

该平面物体的顶点坐标与法向量数据都是存储在同一个数组中的。该平面为一个垂直于z轴并且过原点的平面,其法向量与z轴正方向相同。

create_pipeline_layout方法部分相关代码

//创建管线layout
void ShaderQueueSuit_Common::create_pipeline_layout(VkDevice& device)
{//此方法中主要是更改了一致变量缓冲的目标着色器阶段,将原来的VK_SHADER_STAGE_VERTEX_BIT(顶点着色器阶段)替换为VK_SHADER_STAGE_FRAGMENT _BIT(片元着色器阶段)。//替换的主要目的是将摄像机位置一致变量、光源位置一致变量和光照强度一致变量送入片元着色器,从而在片元着色器中进行光照计算。GMENT _BIT(片元着色器阶段)。VkDescriptorSetLayoutBinding layout_bindings[1];//描述集布局绑定数组layout_bindings[0].binding = 0;//此绑定的绑定点编号layout_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;//描述类型layout_bindings[0].descriptorCount = 1;//描述数量layout_bindings[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;layout_bindings[0].pImmutableSamplers = NULL;VkDescriptorSetLayoutCreateInfo descriptor_layout = {};	//构建描述集布局创建信息结构体实例descriptor_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;//结构体类型descriptor_layout.pNext = NULL;//自定义数据的指针descriptor_layout.bindingCount = 1;//描述集布局绑定的数量descriptor_layout.pBindings = layout_bindings;//描述集布局绑定数组//调整空间descLayouts.resize(NUM_DESCRIPTOR_SETS);//调整描述集布局列表尺寸VkResult result = vkCreateDescriptorSetLayout(device, &descriptor_layout, NULL, descLayouts.data());//创建描述集布局assert(result == VK_SUCCESS);//检查描述集布局创建是否成功VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {};//构建管线布局创建信息结构体实例pPipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;	pPipelineLayoutCreateInfo.pNext = NULL;//自定义数据的指针pPipelineLayoutCreateInfo.pushConstantRangeCount = 0;pPipelineLayoutCreateInfo.pPushConstantRanges = NULL;pPipelineLayoutCreateInfo.setLayoutCount = NUM_DESCRIPTOR_SETS;//描述集布局的数量pPipelineLayoutCreateInfo.pSetLayouts = descLayouts.data();//描述集布局列表result = vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, NULL, &pipelineLayout);//创建管线布局assert(result == VK_SUCCESS);//检查创建是否成功
}

commonTextLight.vert

#version 450
#extension GL_ARB_separate_shader_objects : enable//开启separate_shader_objects
#extension GL_ARB_shading_language_420pack : enable	//开启shading_language_420pack
layout (push_constant) uniform constantVals {//一致块mat4 mvp;//最终变换矩阵mat4 mm;//基本变换矩阵
} myConstantVals;
layout (location = 0) in vec3 pos;//传入的顶点位置
layout (location = 1) in vec3 inNormal; //传入的顶点法向量
//声明的输出变量vposition用于将世界坐标系下的顶点坐标传入片元着色器,以备在片元着色器中计算光照时使用。
layout (location = 1) out vec3 vposition;//输出的顶点位置
layout (location = 2) out vec3 vNormal; //传出的世界坐标系法向量
//。而声明的输出变量objPos用于将物体坐标系下的顶点坐标传入片元着色器,以备计算棋盘着色的时候使用。
layout (location = 3) out vec3 objPos; //传出的物体坐标系顶点坐标
out gl_PerVertex {//输出接口块vec4 gl_Position;//顶点最终位置
};
//新增的将物体坐标系法向量变换到世界坐标系的normalFromObjectToWorld方法,此方法中的具体操作与前面案例中对应的部分基本相同。
vec3 normalFromObjectToWorld( //将物体坐标系的法向量变换到世界坐标系的方法in mat4 uMMatrix, //基本变换矩阵in vec3 normal, //法向量in vec3 position){ //顶点位置vec3 normalTarget=position+normal; //计算变换后的法向量vec3 newNormal=(uMMatrix*vec4(normalTarget,1)).xyz-(uMMatrix*vec4(position,1)).xyz;newNormal=normalize(newNormal); //对法向量规格化return newNormal; //返回世界坐标系法向量}
void main(){//主函数gl_Position = myConstantVals.mvp * vec4(pos,1.0);//计算顶点最终位置vposition=(myConstantVals.mm*vec4(pos,1)).xyz; //计算世界坐标系顶点位置vNormal = normalFromObjectToWorld(myConstantVals.mm,inNormal,pos);//计算世界坐标系法向量objPos=pos; //传送到片元着色器的物体坐标系顶点位置
}

commonTexLigh.frag

//在片元着色器中执行光照计算时的大部分操作与在顶点着色器中进行光照计算时完全相同。
#version 450
#extension GL_ARB_separate_shader_objects : enable//开启separate_shader_objects
#extension GL_ARB_shading_language_420pack : enable//开启shading_language_420pack
layout (std140,set = 0, binding = 0) uniform bufferVals { //一致块
vec4 uCamera; //摄像机位置
vec4 lightPosition; //光源位置
vec4 lightAmbient; //环境光强度
vec4 lightDiffuse; //散射光强度
vec4 lightSpecular; //镜面光强度
} myBufferVals;
layout (location = 1) in vec3 vposition;//顶点着色器传入的顶点位置
layout (location = 2) in vec3 vNormal; //传入的世界坐标系法向量
layout (location = 3) in vec3 objPos; //传入的物体坐标系顶点位置
layout (location = 0) out vec4 outColor;//输出到渲染管线的片元颜色值
vec4 genBoardColor(vec3 position){const float height=4.0;//球的半径const float width=6.0;vec4 color;//结果颜色float n = 8.0;//球体外接立方体每个坐标轴方向切分的份数float spanh = height/n;//每一份的尺寸(小方块的边长)float spanw = width/n;//为了保证不出现负数int i = int((position.x + 10.0)/spanw);//当前片元位置小方块的行数int j = int((position.y + 10.0)/spanh);//当前片元位置小方块的层数//计算当前片元行数、层数、列数的和并对2取模int whichColor = int(mod(float(i+j),2.0));if(whichColor == 1){	//奇数时为颜色Acolor = vec4(0.678,0.231,0.129,1.0);//红色}else {//偶数时为白色color = vec4(1.0,1.0,1.0,1.0);//白色}return color;//返回结果颜色
}
vec4 pointLight( //定位光光照计算的方法//最主要的区别是计算光照时不需要再将法向量由物体坐标系变换到世界坐标系了,直接使用顶点着色器传递过来的世界坐标系中的法向量即可//因此每片元计算光照与每顶点计算光照并没有本质区别,只是执行光照计算的位置不同、效果与效率不同而已。实际开发中读者应该权衡速度、效果的要求,选用合适的光照计算策略。in vec3 uCamera, //摄像机位置in vec3 lightLocation, //光源位置in vec4 lightAmbient, //环境光强度in vec4 lightDiffuse, //散射光强度in vec4 lightSpecular, //镜面光强度in vec3 normal, //法向量in vec3 aPosition){ //顶点位置vec4 ambient; //环境光最终强度vec4 diffuse; //散射光最终强度vec4 specular; //镜面光最终强度ambient=lightAmbient; //直接得出环境光的最终强度vec3 eye= normalize(uCamera-aPosition); //计算从表面点到摄像机的向量vec3 vp= normalize(lightLocation.xyz-aPosition); //计算从表面点到光源位置的向量vpvp=normalize(vp); //格式化vp 向量vec3 halfVector=normalize(vp+eye); //求视线与vp 向量的半向量float shininess=10.0; //粗糙度,越小越光滑float nDotViewPosition=max(0.0,dot(normal,vp)); //求法向量与vp 的点积与0 的最大值diffuse=lightDiffuse*nDotViewPosition; //计算散射光的最终强度float nDotViewHalfVector=dot(normal,halfVector); //法向量与半向量的点积float powerFactor=max(0.0,pow(nDotViewHalfVector,shininess)); //镜面反射光强度因子specular=lightSpecular*powerFactor; //计算镜面光的最终强度return ambient+diffuse+specular; //将三个光照通道最终强度值求和返回
}
void main(){//主方法vec4 lightQD=pointLight( //定位光光照计算的方法myBufferVals.uCamera.xyz, //摄像机位置myBufferVals.lightPosition.xyz, //光源位置myBufferVals.lightAmbient, //环境光强度myBufferVals.lightDiffuse, //散射光强度myBufferVals.lightSpecular, //镜面光强度vNormal, //世界坐标系法向量vposition ); //世界坐标系顶点位置outColor=genBoardColor(objPos)*lightQD; //计算片元最终颜色值
}

在这里插入图片描述

commonTexLight.vert

#version 400
#extension GL_ARB_separate_shader_objects : enable//开启separate_shader_objects
#extension GL_ARB_shading_language_420pack : enable	//开启shading_language_420pack
layout (std140,set = 0, binding = 0) uniform bufferVals {vec4 uCamera; vec4 lightPosition; vec4 lightAmbient; vec4 lightDiffuse; vec4 lightSpecular; 
} myBufferVals;
layout (push_constant) uniform constantVals {//一致块mat4 mvp;//最终变换矩阵mat4 mm;//基本变换矩阵
} myConstantVals;
layout (location = 0) in vec3 pos;//传入的顶点位置
layout (location = 1) in vec3 inNormal; //传入的顶点法向量
layout (location = 0) out vec4 outLightQD; 
layout (location = 1) out vec3 vposition;//输出的顶点位置
out gl_PerVertex {//输出接口块vec4 gl_Position;//顶点最终位置
};
vec4 pointLight( in mat4 uMMatrix, //基本变换矩阵in vec3 uCamera, in vec3 lightLocation, in vec4 lightAmbient, in vec4 lightDiffuse, in vec4 lightSpecular, in vec3 normal, //法向量in vec3 aPosition 
){vec4 ambient; vec4 diffuse; vec4 specular; ambient=lightAmbient; vec3 normalTarget=aPosition+normal; vec3 newNormal=(uMMatrix*vec4(normalTarget,1)).xyz-(uMMatrix*vec4(aPosition,1)).xyz;newNormal=normalize(newNormal); //对法向量规格化vec3 eye= normalize(uCamera-(uMMatrix*vec4(aPosition,1)).xyz); vec3 vp= normalize(lightLocation-(uMMatrix*vec4(aPosition,1)).xyz);vp=normalize(vp); vec3 halfVector=normalize(vp+eye); float shininess=50.0; float nDotViewPosition=max(0.0,dot(newNormal,vp)); diffuse=lightDiffuse*nDotViewPosition; float nDotViewHalfVector=dot(newNormal,halfVector); float powerFactor=max(0.0,pow(nDotViewHalfVector,shininess)); specular=lightSpecular*powerFactor; return ambient+diffuse+specular; }
void main(){//主函数outLightQD=pointLight( myConstantVals.mm, myBufferVals.uCamera.xyz, myBufferVals.lightPosition.xyz, myBufferVals.lightAmbient, myBufferVals.lightDiffuse, myBufferVals.lightSpecular, inNormal, pos );gl_Position = myConstantVals.mvp * vec4(pos,1.0);//计算顶点最终位置vposition=pos; 
}

commonTexLight.frag

#version 400
#extension GL_ARB_separate_shader_objects : enable//开启separate_shader_objects
#extension GL_ARB_shading_language_420pack : enable//开启shading_language_420pack
layout (location = 0) in vec4 inLightQD;
layout (location = 1) in vec3 vposition;//顶点着色器传入的顶点位置
layout (location = 0) out vec4 outColor;//输出到渲染管线的片元颜色值
vec4 genBoardColor(vec3 position)
{const float height=4.0;//球的半径const float width=6.0;vec4 color;//结果颜色float n = 8.0;//球体外接立方体每个坐标轴方向切分的份数float spanh = height/n;//每一份的尺寸(小方块的边长)float spanw = width/n;//为了保证不出现负数int i = int((position.x + 10.0)/spanw);//当前片元位置小方块的行数int j = int((position.y + 10.0)/spanh);//当前片元位置小方块的层数//计算当前片元行数、层数、列数的和并对2取模int whichColor = int(mod(float(i+j),2.0));if(whichColor == 1){	//奇数时为颜色Acolor = vec4(0.678,0.231,0.129,1.0);//红色}else {//偶数时为白色color = vec4(1.0,1.0,1.0,1.0);//白色}return color;//返回结果颜色
}void main() {outColor=inLightQD*genBoardColor(vposition);
}

在这里插入图片描述