OpenGL學習筆記(十)Material類(材質)

在真實世界裏,每個物體會對光產生不同的反應。鋼看起來比陶瓷花瓶更閃閃發光,一個木頭箱子不會像鋼箱子一樣對光產生很強的反射。每個物體對鏡面高光也有不同的反應。有些物體不會散射(Scatter)很多光卻會反射(Reflect)很多光,結果看起來就有一個較小的高光點(Highlight),有些物體散射了很多,它們就會產生一個半徑更大的高光。如果我們想要在OpenGL中模擬多種類型的物體,我們必須爲每個物體分別定義材質(Material)屬性。
所以我們來寫一個Material類來控制Material吧!
先是fragmentSource.txt

#version 330 core			
out vec4 FragColor;		
in vec3 FragPos;
in vec3 Normal;
//設置一個材質結構體
struct Material{
vec3 ambient;//環境
vec3 diffuse;//漫反射
vec3 specular;//鏡面反射
float shininess;//鏡面反射光澤
};
uniform Material material;//聲明一個材質球
uniform vec3 objColor;
uniform vec3 ambientColor;
uniform vec3 lightPos;
uniform vec3 lightColor;
uniform vec3 CameraPos;
void main()				
{
vec3 norm=normalize(Normal);

vec3 lightDir=normalize(lightPos-FragPos);
vec3 diffuse =max(dot(norm,lightDir), 0.0f) * lightColor*material.diffuse;//通過diffuse控制漫反射強度

vec3 reflectVec=reflect(-lightDir,norm);
vec3 CameraVec=normalize(CameraPos-FragPos);
vec3 specular=pow(max(dot(reflectVec,CameraVec),0.0f),material.shininess)*lightColor*material.specular;//通過shininess和specular控制鏡面反射強度
vec3 ambient=ambientColor*material.ambient;//通過ambient控制環境光強度
vec3 result=(ambient+diffuse+specular)*objColor;//計算更改過後的整體光照

FragColor = vec4(result,1.0f);
}	

Material.h

#pragma once
#include "Shader.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
class Material
{
public:
	Shader* shader;//材質球需要確定對哪個shader進行操作
	glm::vec3 ambient;//環境光控制
	glm::vec3 diffuse; //漫反射控制
	glm::vec3 specular; //鏡面反射控制
	float shininess;鏡面反射光澤
	Material(Shader* _shader, glm::vec3 _ambient, glm::vec3 _diffuse, glm::vec3 _specular, float _shininess);
};

Material.cpp

#include "Material.h"

Material::Material(Shader* _shader, glm::vec3 _ambient, glm::vec3 _diffuse, glm::vec3 _specular, float _shininess)
	:shader(_shader),ambient(_ambient),diffuse(_diffuse),specular(_specular),shininess(_shininess)//構造函數
{
}

還需要改一下Shader類
Shader.h增加

public:
	void SetUniform3f(const char* paramNameString, glm::vec3 param);
	void SetUniform1f(const char* paramNameString, float param);

Shader.cpp

void Shader::SetUniform3f(const char* paramNameString, glm::vec3 param)//通過直接給予一個vec3傳入uniform參數
{ 
	glUniform3f(glGetUniformLocation(ID, paramNameString), param.x, param.y, param.z);
}
void Shader::SetUniform1f(const char* paramNameString, float param)//只是爲了隊形統一
{
	glUniform1f(glGetUniformLocation(ID, paramNameString), param);

然後是主函數
main.cpp
循環外面:

Material* myMaterial = new Material(myShader,
		glm::vec3(1.0f,1.0f,1.0f),
		glm::vec3(0.0f, 0.0f, 1.0f),
		glm::vec3(0.0f, 1.0f, 0.0f),
		32.0f
		);//聲明一個Material

循環裏面:

	         glm::vec3 lightColor;//控制燈光的向量
			lightColor.x = sin(glfwGetTime()* 2.0f);//通過時間改變燈光的紅色
			lightColor.y = sin(glfwGetTime() * 0.7f);//通過時間改變燈光的綠色
			lightColor.z = sin(glfwGetTime() * 1.3f);//通過時間改變燈光的藍色
			glm::vec3 diffuseColor = lightColor * glm::vec3(0.5f);//通過改變後的燈光顏色同時改變漫反射顏色
			glm::vec3 specularColor = diffuseColor * glm::vec3(1.0f);//同時改變鏡面反射顏色
            //控制材質球的變量
			glUniform3f(glGetUniformLocation(myShader->ID, "lightColor"), lightColor.x, lightColor.y, lightColor.z);
			myMaterial->shader->SetUniform3f("material.ambient", myMaterial->ambient);
			myMaterial->shader->SetUniform3f("material.diffuse", diffuseColor);
			myMaterial->shader->SetUniform3f("material.specular", specularColor);
			myMaterial->shader->SetUniform1f("material.shininess", myMaterial->shininess);

最終效果圖,不會放視頻,只能截圖啦:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章