OpenGL-- Shader 颜色 光照


参考:

http://learnopengl-cn.readthedocs.io/zh/latest/02%20Lighting/02%20Basic%20Lighting/



1. 主程序                                                    


#include 

#define GLEW_STATIC
#include 

#include 

#include "Shader.h"
#include "Camera.h"

#include 
#include 
#include 

#include 

#include 

#define GLEW_STATIC
#include 
#include 

#include 
#include 
#include 

#include "TextureShader.h"

#pragma comment(lib, "./SOIL.lib")

#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glew32s.lib")
#pragma comment (lib, "glfw3.lib") 
#pragma comment (lib, "glfw3dll.lib") 
#pragma comment (lib, "glew32mxs.lib")

void key_callback(GLFWwindow* pWnd, int key, int scancode, int action, int mode);
void mouse_callback(GLFWwindow* pWnd, double xpos, double ypos);
void scroll_callback(GLFWwindow* pWnd, double xoffset, double yoffset);
void do_movement();

const GLuint WIDTH = 800, HEIGHT = 600;


Camera  camera(glm::vec3(0.0f, 0.0f, 3.0f));
GLfloat lastX = WIDTH / 2.0;
GLfloat lastY = HEIGHT / 2.0;
bool    keys[1024];

glm::vec3 lightPos(1.2f, 1.0f, 2.0f);

GLfloat deltaTime = 0.0f;
GLfloat lastFrame = 0.0f;

/////////////////////////////////////////////////////////////////////////
int main()
{
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

	GLFWwindow* pWnd = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
	glfwMakeContextCurrent(pWnd);

	glfwSetKeyCallback(pWnd, key_callback);
	glfwSetCursorPosCallback(pWnd, mouse_callback);
	glfwSetScrollCallback(pWnd, scroll_callback);

	// 鼠标隐藏
	//glfwSetInputMode(pWnd, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

	glewExperimental = GL_TRUE;
	glewInit();
	glViewport(0, 0, WIDTH, HEIGHT);
	glEnable(GL_DEPTH_TEST);

	Shader lightingObjShader("./obj_vertex", "./obj_fragement");
	Shader lampShader("./lamp_vertex", "./lamp_fragement");

	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 objPos[] = {
		glm::vec3(-3.0f,  -1.0f,  -5.0f),           glm::vec3(2.0f,  5.0f, -1.0f),
		glm::vec3(-1.5f, -2.2f, -2.5f),         glm::vec3(0.0f, -2.0f, -5.3f),
		glm::vec3(2.4f, -0.4f, -3.5f),          glm::vec3(-1.7f,  0.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)	};

	GLuint VBO, objVAO;
	glGenVertexArrays(1, &objVAO);
	glGenBuffers(1, &VBO);

	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);		// 顶点复至GPU中

	// 光照物体
	glBindVertexArray(objVAO); // --- Begin
	// 位置索引
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
	glEnableVertexAttribArray(0);
	// 向量索引
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
	glEnableVertexAttribArray(1);
	glBindVertexArray(0); // --- End

	// 灯泡 (只需要用到一部分坐标点数据,用于绘制一个立方体即可)
	GLuint lampVAO;
	glGenVertexArrays(1, &lampVAO);
	glBindVertexArray(lampVAO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
	glEnableVertexAttribArray(0);
	glBindVertexArray(0);
	
	GLuint  nCurrentTime = glfwGetTime();
	GLuint nLastTime = glfwGetTime();
	GLuint nFPS = 0;

	while (!glfwWindowShouldClose(pWnd))
	{
		GLfloat currentFrame = glfwGetTime();
		deltaTime = currentFrame - lastFrame;
		lastFrame = currentFrame;

		glfwPollEvents();

		do_movement();

		glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		// 视图设置
		glm::mat4 view;
		view = camera.GetViewMatrix();
		glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);

		// -----------------------------------------------
		// 绘制光照物体
		lightingObjShader.useShaderPrograme();
		GLint objectColorLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "objectColor");
		GLint lightColorLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "lightColor");
		GLint lightPosLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "lightPos");
		GLint viewPosLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "viewPos");
		glUniform3f(objectColorLoc, 1.0f, 0.5f, 0.31f);		// 物体颜色
		glUniform3f(lightColorLoc, 1.0f, 1.0f, 1.0f);				// 光照颜色
		glUniform3f(lightPosLoc, lightPos.x, lightPos.y, lightPos.z);		// 灯光位置
		glUniform3f(viewPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);	// 观察点位置
		
		GLint modelLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "model");
		GLint viewLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "view");
		GLint projLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "projection");
		// Pass the matrices to the shader
		glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
		glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

		glm::mat4 model = glm::mat4();

		glBindVertexArray(objVAO);	// --- Begin
		for (GLuint i = 0; i < 10; i++)
		{			
			model = glm::mat4();
			model = glm::translate(model, objPos[i]);
			GLfloat angle = glfwGetTime();
			model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));
			glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

			glDrawArrays(GL_TRIANGLES, 0, 36);
		}
		glBindVertexArray(0);	// --- End
		// -----------------------------------------------

		// -----------------------------------------------
		// 绘制灯泡
		lampShader.useShaderPrograme();
		modelLoc = glGetUniformLocation(lampShader.getPrograme(), "model");
		viewLoc = glGetUniformLocation(lampShader.getPrograme(), "view");
		projLoc = glGetUniformLocation(lampShader.getPrograme(), "projection");

		glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
		glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

		model = glm::mat4();
		model = glm::translate(model, lightPos);
		model = glm::scale(model, glm::vec3(0.2f)); // Make it a smaller cube
		glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
		
		glBindVertexArray(lampVAO);	// --- Begin
		glDrawArrays(GL_TRIANGLES, 0, 36);
		glBindVertexArray(0);	// --- End
		// -----------------------------------------------

		// Swap the screen buffers
		glfwSwapBuffers(pWnd);
		nLastTime = glfwGetTime();
		nFPS++;
		if (nLastTime - nCurrentTime > 1)
		{
			std::cout << "当前帧率:" << nFPS << std::endl;
			nFPS = 0;
			nCurrentTime = nLastTime;
		}
	}

	// Terminate GLFW, clearing any resources allocated by GLFW.
	glfwTerminate();
	return 0;
}

// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* pWnd, int key, int scancode, int action, int mode)
{
	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
		glfwSetWindowShouldClose(pWnd, GL_TRUE);
	if (key >= 0 && key < 1024)
	{
		if (action == GLFW_PRESS)
			keys[key] = true;
		else if (action == GLFW_RELEASE)
			keys[key] = false;
	}
}

void do_movement()
{
	// Camera controls
	if (keys[GLFW_KEY_W])
		camera.ProcessKeyboard(FORWARD, deltaTime);
	if (keys[GLFW_KEY_S])
		camera.ProcessKeyboard(BACKWARD, deltaTime);
	if (keys[GLFW_KEY_A])
		camera.ProcessKeyboard(LEFT, deltaTime);
	if (keys[GLFW_KEY_D])
		camera.ProcessKeyboard(RIGHT, deltaTime);
}

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

	GLfloat xoffset = xpos - lastX;
	GLfloat yoffset = lastY - ypos;  // Reversed since y-coordinates go from bottom to left

	lastX = xpos;
	lastY = ypos;

	//camera.ProcessMouseMovement(xoffset, yoffset);
}

void scroll_callback(GLFWwindow* pWnd, double xoffset, double yoffset)
{
	camera.ProcessMouseScroll(yoffset);
}




2. Shader设置                                                    


#pragma once

#ifndef TEXTURE_SHADER_H_
#define TEXTURE_SHADER_H_

#include 
#include 
#include 
#include 

#include 

#include 
#include 
#include 
#include 

#include 

class Shader
{
public:
	Shader(const GLchar* vertexPath, const GLchar* fragmentPath);
	~Shader();

public:
	void useShaderPrograme();

	GLuint getPrograme() {
		return this->m_nProgram;
	}

private:
	GLuint  m_nProgram;
};

Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
{
	std::string vertexCode;
	std::string fragmentCode;
	std::ifstream vertexShaderF;
	std::ifstream fragementShaderF;

	vertexShaderF.exceptions(std::ifstream::badbit);
	fragementShaderF.exceptions(std::ifstream::badbit);

	try
	{
		vertexShaderF.open(vertexPath);		// 打开文件
		fragementShaderF.open(fragmentPath);

		std::stringstream vertexShaderStream, fragementShaderStream;
		vertexShaderStream << vertexShaderF.rdbuf();	// 读取文件至stringstream中
		fragementShaderStream << fragementShaderF.rdbuf();

		vertexShaderF.close();
		fragementShaderF.close();

		vertexCode = vertexShaderStream.str();		// 转换成string类型
		fragmentCode = fragementShaderStream.str();
	}
	catch (std::ifstream::failure e)
	{
		std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ:" << std::endl;
	}

	const GLchar* pVertexCode = vertexCode.c_str();	// string 转 char*
	const GLchar* pFragementCode = fragmentCode.c_str();

	GLuint nVertexShader, nFragementShader;
	GLint nRes = 0;
	GLchar chLogInfo[512] = { '\0' };

	// 创建顶点着色器
	nVertexShader = glCreateShader(GL_VERTEX_SHADER);
	// 将顶点着色程序的源代码字符数组绑定到顶点着色器对象
	glShaderSource(nVertexShader, 1, &pVertexCode, nullptr);
	glCompileShader(nVertexShader); // compile shader 编译着色器

	// 获取编译结果
	glGetShaderiv(nVertexShader, GL_COMPILE_STATUS, &nRes);
	if (!nRes)
	{
		glGetShaderInfoLog(nVertexShader, 512, nullptr, chLogInfo);
		std::cout << "ERROR::SHADEF::VERTEX::COMPILATION_FAILED:" << chLogInfo << std::endl;
	}

	// 创建片断着色器
	nFragementShader = glCreateShader(GL_FRAGMENT_SHADER);
	// 将片段着色程序的源代码字符数组绑定到片段着色器对象
	glShaderSource(nFragementShader, 1, &pFragementCode, nullptr);
	glCompileShader(nFragementShader);
	glGetShaderiv(nFragementShader, GL_COMPILE_STATUS, &nRes);
	if (!nRes)
	{
		glGetShaderInfoLog(nFragementShader, 512, nullptr, chLogInfo);
		std::cout << "ERROR::SHADEF::FRAGEMENT::COMPILATION_FAILED:" << chLogInfo << std::endl;
	}

	this->m_nProgram = glCreateProgram();	// 创建GLSL程序
	glAttachShader(this->m_nProgram, nVertexShader);	// 绑定shader到program
	glAttachShader(this->m_nProgram, nFragementShader);

	// glLinkProgram操作产生最后的可执行程序,它包含最后可以在硬件上执行的硬件指令
	glLinkProgram(this->m_nProgram);		// 链接
	glGetProgramiv(this->m_nProgram, GL_LINK_STATUS, &nRes);
	if (!nRes)
	{
		glGetProgramInfoLog(this->m_nProgram, 512, nullptr, chLogInfo);
		std::cout << "ERROR::SHADEF::FRAGEMENT::LINK_FAILED:" << chLogInfo << std::endl;
	}

	glDeleteShader(nVertexShader);
	glDeleteShader(nFragementShader);
}

Shader::~Shader()
{
}

#include 
#include 
#include 

void Shader::useShaderPrograme()
{
	glUseProgram(this->m_nProgram);	// 使用porgram
}

#endif




3.Camera.h                                              


#pragma once

// Std. Includes
#include 

// GL Includes
#include 
#include 
#include 



// Defines several possible options for camera movement. Used as abstraction to stay away from pWnd-system specific input methods
enum Camera_Movement {
	FORWARD,
	BACKWARD,
	LEFT,
	RIGHT
};

// Default camera values
const GLfloat YAW = -90.0f;
const GLfloat PITCH = 0.0f;
const GLfloat SPEED = 3.0f;
const GLfloat SENSITIVTY = 0.25f;
const GLfloat ZOOM = 45.0f;


// An abstract camera class that processes input and calculates the corresponding Eular Angles, Vectors and Matrices for use in OpenGL
class Camera
{
public:
	// Camera Attributes
	glm::vec3 Position;
	glm::vec3 Front;
	glm::vec3 Up;
	glm::vec3 Right;
	glm::vec3 WorldUp;
	// Eular Angles
	GLfloat Yaw;
	GLfloat Pitch;
	// Camera options
	GLfloat MovementSpeed;
	GLfloat MouseSensitivity;
	GLfloat Zoom;

	// Constructor with vectors
	Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), GLfloat yaw = YAW, GLfloat pitch = PITCH) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
	{
		this->Position = position;
		this->WorldUp = up;
		this->Yaw = yaw;
		this->Pitch = pitch;
		this->updateCameraVectors();
	}
	// Constructor with scalar values
	Camera(GLfloat posX, GLfloat posY, GLfloat posZ, GLfloat upX, GLfloat upY, GLfloat upZ, GLfloat yaw, GLfloat pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
	{
		this->Position = glm::vec3(posX, posY, posZ);
		this->WorldUp = glm::vec3(upX, upY, upZ);
		this->Yaw = yaw;
		this->Pitch = pitch;
		this->updateCameraVectors();
	}

	// Returns the view matrix calculated using Eular Angles and the LookAt Matrix
	glm::mat4 GetViewMatrix()
	{
		return glm::lookAt(this->Position, this->Position + this->Front, this->Up);
	}

	// Processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems)
	void ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime)
	{
		GLfloat velocity = this->MovementSpeed * deltaTime;
		if (direction == FORWARD)
			this->Position += this->Front * velocity;
		if (direction == BACKWARD)
			this->Position -= this->Front * velocity;
		if (direction == LEFT)
			this->Position -= this->Right * velocity;
		if (direction == RIGHT)
			this->Position += this->Right * velocity;
	}

	// Processes input received from a mouse input system. Expects the offset value in both the x and y direction.
	void ProcessMouseMovement(GLfloat xoffset, GLfloat yoffset, GLboolean constrainPitch = true)
	{
		xoffset *= this->MouseSensitivity;
		yoffset *= this->MouseSensitivity;

		this->Yaw += xoffset;
		this->Pitch += yoffset;

		// Make sure that when pitch is out of bounds, screen doesn't get flipped
		if (constrainPitch)
		{
			if (this->Pitch > 89.0f)
				this->Pitch = 89.0f;
			if (this->Pitch < -89.0f)
				this->Pitch = -89.0f;
		}

		// Update Front, Right and Up Vectors using the updated Eular angles
		this->updateCameraVectors();
	}

	// Processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis
	void ProcessMouseScroll(GLfloat yoffset)
	{
		if (this->Zoom >= 1.0f && this->Zoom <= 45.0f)
			this->Zoom -= yoffset;
		if (this->Zoom <= 1.0f)
			this->Zoom = 1.0f;
		if (this->Zoom >= 45.0f)
			this->Zoom = 45.0f;
	}

private:
	// Calculates the front vector from the Camera's (updated) Eular Angles
	void updateCameraVectors()
	{
		// Calculate the new Front vector
		glm::vec3 front;
		front.x = cos(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
		front.y = sin(glm::radians(this->Pitch));
		front.z = sin(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
		this->Front = glm::normalize(front);
		// Also re-calculate the Right and Up vector
		this->Right = glm::normalize(glm::cross(this->Front, this->WorldUp));  // Normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.
		this->Up = glm::normalize(glm::cross(this->Right, this->Front));
	}
};



4.灯泡顶点着色器 lamp_vertex                                  


#version 330 core
layout (location = 0) in vec3 position;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f);

}



5.灯泡片断着色器lamp_fragement                            


#version 330 core
out vec4 color;




in vec3 Normal;


void main()
{
    color = vec4(1.0f); // 灯泡为白色
}



6.物体顶点着色器 obj_vertex                                 


#version 330 core

// 位置顶点 及 位置顶点的向量
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

out vec3 FragPos;
out vec3 Normal;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f);
	FragPos = vec3(model * vec4(position, 1.0f));
    Normal = normal;
}






7.物体片断着色器 obj_fragement                      



#version 330 core

in vec3 FragPos;
in vec3 Normal;  

out vec4 color;

uniform vec3 lightPos; 

uniform vec3 objectColor;
uniform vec3 lightColor;


void main()
{
	// Ambient 环境光强度为灯光的0.1
    float ambientStrength = 0.1f;
    vec3 ambient = ambientStrength * lightColor;

    // Diffuse  漫反射强度
	//			为光线到物体的向量 与 物体表面向量 的点乘
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(lightPos - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);

    vec3 diffuse = diff * lightColor;

	// 最终光线为 (环境光强 + 漫反射光强) 与物体颜色的乘积
    vec3 result = (ambient + diffuse) * objectColor;
    color = vec4(result, 1.0f);
}

OpenGL-- Shader 颜色 光照_第1张图片



OpenGL-- Shader 颜色 光照_第2张图片





你可能感兴趣的:(OpenGL,C++)