OpenGL学习之基础光照

Phong模型

简单光照明模拟物体表面对光的反射作用。

光源为点光源。

反射作用分为

环境光(Ambient Light)

漫反射(Diffuse Reflection)

镜面反射(Specular Reflection)

 

环境光(Ambient Light)

 在没有光源的地方,景物没有受到光源的直接照射,但其表面仍有一定的亮度,使它们可见。这是因为光线在场景中经过复杂的传播之后,形成了弥漫于整个空间的光线,称之为环境光。

环境光是指光源间接对物体的影响

光在物体和环境之间多次反射,最终达到平衡

同一环境下的环境光光强分布均匀

近似表示为:Ie=Ia∙Ka(其中,Ia为环境光强度,Ka为物体对环境光的反射系数)

使用光的颜色乘以一个很小的常量因子,再乘以物体的颜色,然后将最后结果作为片段的颜色:

void main()
{
     float ambientStrength = 0.1;
     vec3 ambient = ambientStrength * lightColor;

     vec3 result = ambient * objectColor;
     FragColor = vec4(result,1.0)

}

漫反射

点光源是位于空间某个位置的一个点,向周围所有的方向上辐射等光强的光,记其光强为Ip.

在点光源的照射下,物体表面的不同部分亮度不同,亮度的大小依赖于它的朝向以及它与点光源之间的距离。

理想漫反射

在一个粗糙的、无光泽的表面呈现为漫反射。当光线照射到这样的表面时,光线沿各个方向都作相同的反射,所以从任何角度去看这种表面都有相同的亮度。

漫反射的特点:光源来自一个方向,反射光均匀地射向各个方向,与视点无关。

由Lambert余弦定律,漫反射光强为Id=IpKd×cosθ

其中:Ip是入射光的强度;  Kd是不物体有关的漫反射系数,0< Kd <1;
          θ是L和N的夹角 0≤θ≤π/2 ;  L是P点指向光源的方向矢量
         N是物体表面在P点的法矢量

其中:0≤θ≤π/2,当θ = 0时,物体表面正好垂直于光线方向,这时获得的光照强度最大;当θ = 90时物体表面与光线方向平行,此时光线照射不到物体,光的强度最弱;当θ>90后,物体的表面转向到光线的背面,此时物体对应的表面接受不到光照。

将L和N觃格化为单位矢量则cosθ=(L∙N)

漫反射光强为Id=IpKd× (L∙N)

 多个点光源

漫反射的光强为:

 法向量

法向量是一个垂直于顶点表面的(单位)向量。法向量通过顶点属性里指定经过模型和视变换后需要重新计算。使用叉乘对所有的立方体顶点计算法向量,但由于3D立方体不是一个复杂的形状,所以我们可以简单地把法向量数据手工添加到顶点数据中。

float vertices[] = {
    -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
     0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f, 
     0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f, 
     0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f, 
    -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f, 
    -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f, 

    -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
     0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
     0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
     0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
    -0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
    -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,

    -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
    -0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
    -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
    -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
    -0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
    -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,

     0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
     0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
     0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
     0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
     0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
     0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,

    -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
     0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
     0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
     0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
    -0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,

    -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
     0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
     0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
     0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
    -0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
    -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f
};

 和顶点位置属性一样,我们需要将法向量数据发送到GPU,并且使用glVertexAttribPointer告诉OpenGL数据的解析方式。

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

将顶点属性传递到着色器后,需要在着色器中开始光照计算。有两种方法执行向量L和N的计算。一种方式是在世界坐标系中计算,另一种是在相机坐标系中计算,两种方法都可以实现。

以世界坐标系中计算L和N为例进行说明,在相机坐标系中也有类似操作。在世界坐标系中,计算L时,光源lightPos是在世界坐标系中指定的位置,直接使用即可。顶点位置需要变换到世界坐标系中,利用Model矩阵即可,使用式子:FragPos=vec3(model∗vec4(position,1.0));(变换后顶点位置)

在计算N时需要注意,我们不能直接利用Model * normal来获取变换后的法向量,应该使用式子

 

Normal=mat3(transpose(inverse(model)))∗normal(变换后法向量)

 

#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal;

uniform mat4 modelMat;
uniform mat4 viewMat;
uniform mat4 projMat;

out vec3 FragPos;
out vec3  Normal;

void main()
{
    gl_position = projection * view * model * vec4(aPos,1.0);
    FragPos = vec3(model * vec4(aPos,1.0));
    Normal = aNormal;
}

在片元着色器中,计算漫反射光成分的代码为:

#version core 330

in vec3 FragPos;
in vec3 Normal;

uniform vec3 lightPos;
uniform vec3 lightColor;
uniform vec3 objectColor;

void main()
{
    vec3 lightDir = normalize(lightPos - FragPos);
    float diff = max(dot(norm,lightDir),0.0);
    vec3 diffuse = diff *lightColor;
    vec3 result = (ambient + diffuse) * objectColor;
    FragColor=vec4(result,1.0);

}

这里使用max(dot(lightDir,normal),0)主要是为了防止当光线和法向量夹角大于90°后,取值为负,因此使用max保证漫反射光照系数在[0,1.0]范围内。

镜面反射

镜面反射遵循反射定律,反射光位于表面法矢的两侧。

对于理想的高光泽度反射面,反射角等于入射角的时候,光线正好会被反射。这时,如果观察者正好处在P点的镜面反射上,就会看到一个比周围亮得多的一个高光点。

 非理想的反射面,只要其表面是光滑的,在点光源的照射下,也会产生一块特别亮的区域,称为高光点。

尽管这时镜面反射光的强度会随α角的增加而急剧地减少,但观察者还是可以在α角很小的情况下接受这种改变了方向的一部分镜面反射光。

镜面反射的光强可表示为

其中,Ip是入射光强度;Ks是与物体有关的镜面反射系数;α为视点方向V与镜面反射方向R之间的夹角,且V,R均规格化为单位向量cos α =R ∙ V

n为反射指数,反映物体表面的光泽程度,数目越大物体表面越光滑 

多个点光源(m个点光源)

 计算镜面光成分过程为:

在片元着色器中添加一个uniform,把相应的摄像机位置传给片元着色器。

uniform vec3 CameraPos;
// 镜面反射成分 此时需要光线方向为由光源指出
float   specularStrength = 0.5f;
vec3    reflectDir = normalize(reflect(-lightDir, normal));
vec3    viewDir = normalize(viewPos - FragPos);
float specularAmount = pow(max(dot(reflectVec,CameraVec),0),32); // 32为镜面高光系数
vec3    specular = specularStrength * specFactor * lightColor * objectColor;

需要注意的是,利用reflect函数计算光的出射方向时,要求入射方向指向物体表面位置,因此这里反转了lightDir.

pow(max(dot(viewDir, reflectDir), 0.0), 32)中先计算视线方向与反射方向的点乘(并确保它不是负值),然后取它的32次幂。这个32是高光的反光度。一个物体的反光度越高,反射能力越强,散射得越少,高光点就会越小。

Phong光照明模型的综合表述:由物体表面上一点P反射到规点的光强I为环境光的反射光强Ie、理想漫反射光强Id和镜面反射光强Is的总和。I=IaKa+IpKd(L∙N)+IpKs(R∙V)n

将上述三种光成分叠加后,成为最终物体的颜色,片元着色器实现为:

 

 vec3 result = ambient + diffuse + specular 
   color = vec4(result , 1.0f);

vertexSource.txt

#version 330 core
layout (location = 0) in vec3 aPos;
layout(location = 3) in vec3 aNormal;

uniform mat4 modelMat;
uniform mat4 viewMat;
uniform mat4 projMat;


out vec3 FragPos;
out vec3 Normal;

void main()
{
	gl_Position = projMat *  viewMat * modelMat * vec4(aPos, 1.0);
	FragPos= (modelMat * vec4(aPos.xyz,1.0)).xyz;
	Normal = mat3(transpose(inverse(modelMat)))* aNormal;

}

fragmentSource.txt

#version 330 core

in vec3 FragPos;
in vec3 Normal;

uniform vec3 objColor;
uniform vec3 ambientColor;
uniform vec3 lightPos;
uniform vec3 lightColor;
uniform vec3  CameraPos;

out vec4 FragColor;

void main()
{
	vec3 lightDir = normalize(lightPos-FragPos);
	vec3 reflectVec = reflect(-lightDir,Normal);
	vec3 CameraVec = normalize(CameraPos-FragPos);

	float specularAmount = pow(max(dot(reflectVec,CameraVec),0),32);
	vec3 specular = specularAmount*lightColor;
	vec3 diffuse =max( dot(lightDir,Normal),0)*lightColor;
	FragColor = vec4((diffuse + ambientColor + specular) * objColor,1.0);
}

 main.cpp

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>
#include"Shader.h"
#include"Camera.h"

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT =600;

	#pragma region Camera Declare
Camera camera(glm::vec3(0, 0, 3.0f), glm::radians(-15.0f), glm::radians(180.0f), glm::vec3(0, 1.0f, 0));
#pragma endregion

	#pragma region Input Declare
float lastX;
float lastY;
bool firstMouse = true;

void processInput(GLFWwindow *window)
{
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
	{
		glfwSetWindowShouldClose(window, true);
	}
	if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
	{
		camera.speedZ = 0.1f;
	}
	else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
	{
		camera.speedZ = -0.1f;
	}
	else
	{
		camera.speedZ = 0;
		if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		{
			glfwSetWindowShouldClose(window, true);
		}
		if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
		{
			camera.speedX = 0.1f;
		}
		else if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
		{
			camera.speedX = -0.1f;
		}
		else
		{
			camera.speedX = 0;
		}
	}
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
	{
		glfwSetWindowShouldClose(window, true);
	}
	if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS)
	{
		camera.speedY = -0.1f;
	}
	else if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS)
	{
		camera.speedY = 0.1f;
	}
	else
	{
		camera.speedY = 0;
	}
}

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
	// make sure the viewport matches the new window dimensions; note that width and 
	// height will be significantly larger than specified on retina displays.
	glViewport(0, 0, width, height);
}

void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
	if (firstMouse == true)
	{
		lastX = xpos;
		lastY = ypos;
		firstMouse = false;

	}
	float deltaX, deltaY;
	deltaX = xpos - lastX;
	deltaY = ypos - lastY;

	lastX = xpos;
	lastY = ypos;
	camera.ProcessMouseMovement(deltaX, deltaY);

}

#pragma endregion

unsigned int LoadImageToGPU(const char*filename, GLint internalformat, GLenum format, int textureSlot)
{
	unsigned int texBuffer;
	glGenTextures(1, &texBuffer);
	glActiveTexture(GL_TEXTURE0 + textureSlot);
	glBindTexture(GL_TEXTURE_2D, texBuffer);

	int width, height, nrChannels;
	stbi_set_flip_vertically_on_load(true); // tell stb_image.h to flip loaded texture's on the y-axis.
	unsigned char *data = stbi_load(filename, &width, &height, &nrChannels, 0);
	if (data)
	{
		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, width, height, 0, format, GL_UNSIGNED_BYTE, data);
		glGenerateMipmap(GL_TEXTURE_2D);
	}
	else
	{
		std::cout << "Failed to load texture" << std::endl;
	}
	stbi_image_free(data);
	return texBuffer;
}
int main()
{
	#pragma region Open a window
	// glfw: initialize and configure
	// ------------------------------
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

														
	GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
	if (window == NULL)
	{
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);
	glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
	glfwSetCursorPosCallback(window, mouse_callback);
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
	// glad: load all OpenGL function pointers
	// ---------------------------------------
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}

	// configure global opengl state
	// -----------------------------
	glEnable(GL_DEPTH_TEST);
#pragma endregion
	
	
	#pragma region Model Data
	GLfloat vertices[] = {
	-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
	 0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
	 0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
	 0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
	-0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
	-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,

	-0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
	 0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
	 0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
	 0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
	-0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
	-0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,

	-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
	-0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
	-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
	-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
	-0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
	-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,

	 0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
	 0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
	 0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
	 0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
	 0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
	 0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,

	-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
	 0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
	 0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
	 0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
	-0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
	-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,

	-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
	 0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
	 0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
	 0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
	-0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
	-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f
	};

	glm::vec3 cubePositions[] = {
		glm::vec3(0.0f,  0.0f,  0.0f),
		glm::vec3(2.0f,  5.0f, -15.0f),
		glm::vec3(-1.5f, -2.2f, -2.5f),
		glm::vec3(-3.8f, -2.0f, -12.3f),
		glm::vec3(2.4f, -0.4f, -3.5f),
		glm::vec3(-1.7f,  3.0f, -7.5f),
		glm::vec3(1.3f, -2.0f, -2.5f),
		glm::vec3(1.5f,  2.0f, -2.5f),
		glm::vec3(1.5f,  0.2f, -1.5f),
		glm::vec3(-1.3f,  1.0f, -1.5f)
	};
#pragma endregion
	
	#pragma region Init Shader Pragram
	Shader ourShader("VertexSource.vert", "fragmentSource.frag");
#pragma endregion

	#pragma region Init and Load Models to VAO,VBO 
	unsigned int  VAO;
	glGenVertexArrays(1, &VAO);
	glBindVertexArray(VAO);

	unsigned int VBO;
	glGenBuffers(1, &VBO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);


	// position attribute
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);
	
	glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
	glEnableVertexAttribArray(3);

#pragma endregion

	#pragma region Init and Load Texture
	unsigned int texBufferA;
	texBufferA = LoadImageToGPU("container.jpg",GL_RGB,GL_RGB,0);
	unsigned int texBufferB;
	texBufferB = LoadImageToGPU("awesomeface.png",GL_RGBA, GL_RGBA, 1);
#pragma endregion
	// tell opengl for each sampler to which texture unit it belongs to (only has to be done once)
	// -------------------------------------------------------------------------------------------
	#pragma region Prepare MVP matrices
	glm::mat4 modelMat;
	glm::mat4 viewMat;
	glm::mat4 projMat;
	projMat = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
#pragma endregion
	// render loop
	// -----------
	while (!glfwWindowShouldClose(window))
	{
		// input
		processInput(window);

		// clear srceen 
		glClearColor(0, 0, 0, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // also clear the depth buffer now!


		viewMat = camera.GetViewMatrix();
		
		for (unsigned int i = 0; i < 10; i++)
		{
			//set Model Matrix
			modelMat = glm::translate(glm::mat4(1.0f), cubePositions[i]);
			//set View and Project Matrices here

			//set Material->shader program
			ourShader.use();
			//set Material->textures																								
			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_2D, texBufferA);
			glActiveTexture(GL_TEXTURE1);
			glBindTexture(GL_TEXTURE_2D, texBufferB);
			//set material->uniforms
		/*	glUniform1i(glGetUniformLocation(ourShader.ID, "ourTexture"), 0);
			glUniform1i(glGetUniformLocation(ourShader.ID, "ourFace"), 1);*/
			unsigned int modelLoc = glGetUniformLocation(ourShader.ID, "modelMat");
			unsigned int viewLoc = glGetUniformLocation(ourShader.ID, "viewMat");
			unsigned int projectLoc = glGetUniformLocation(ourShader.ID, "projMat");
			glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMat));
			glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(viewMat));
			glUniformMatrix4fv(projectLoc, 1, GL_FALSE, glm::value_ptr(projMat));
			glUniform3f(glGetUniformLocation(ourShader.ID, "objColor"), 1.0f, 0.5f, 0.31f);
			glUniform3f(glGetUniformLocation(ourShader.ID, "ambientColor"), 0.2f, 0.1f, 0.0f);
			glUniform3f(glGetUniformLocation(ourShader.ID, "lightPos"), 10.0f, 10.0f,-5.0f);
			glUniform3f(glGetUniformLocation(ourShader.ID, "lightColor"), 0.5f, 0.3f, 0.3f);
			glUniform3f(glGetUniformLocation(ourShader.ID, "CameraPos"), camera.Position.x, camera.Position.y, camera.Position.z);


			// set Model
			glBindVertexArray(VAO);

			//Drawcall
			glDrawArrays(GL_TRIANGLES, 0, 36);
		}

		//Clean up,prepare for next render loop
		glfwSwapBuffers(window);
		glfwPollEvents();
		camera.UpdataCameraPos();
	}

	// optional: de-allocate all resources once they've outlived their purpose:
	// ------------------------------------------------------------------------
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	// glfw: terminate, clearing all previously allocated GLFW resources.
	// ------------------------------------------------------------------
	glfwTerminate();
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Estelle_Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值