add function to provide interface

This commit is contained in:
ayachi3 2022-12-16 23:05:08 +08:00
parent 759f4ad688
commit f26402461a
8 changed files with 440 additions and 58 deletions

View File

@ -1,20 +1,48 @@
#version 430 core
out vec4 FragColor;
struct Material {
sampler2D texture_diffuse1;
sampler2D texture_specular1;
float shininess;
};
struct Light {
vec3 position;
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct PointLight {
vec3 position;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct SpotLight {
vec3 position;
vec3 direction;
float cutOff;
float outerCutOff;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
#define NR_POINT_LIGHTS 4
in vec3 FragPos;
in vec3 Normal;
@ -22,27 +50,99 @@ in vec2 TexCoords;
uniform vec3 viewPos;
uniform DirLight dirLight;
uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform SpotLight spotLight;
uniform Material material;
uniform Light light;
// function prototypes
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
void main()
{
// ambient
vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;
// diffuse
// properties
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;
// specular
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb;
vec3 result = ambient + diffuse + specular;
// == =====================================================
// Our lighting is set up in 3 phases: directional, point lights and an optional flashlight
// For each phase, a calculate function is defined that calculates the corresponding color
// per lamp. In the main() function we take all the calculated colors and sum them up for
// this fragment's final color.
// == =====================================================
// phase 1: directional lighting
vec3 result = CalcDirLight(dirLight, norm, viewDir);
// phase 2: point lights
for(int i = 0; i < NR_POINT_LIGHTS; i++)
result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
// phase 3: spot light
result += CalcSpotLight(spotLight, norm, FragPos, viewDir);
FragColor = vec4(result, 1.0);
}
// calculates the color when using a directional light.
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// combine results
vec3 ambient = light.ambient * vec3(texture(material.texture_diffuse1, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse1, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.texture_specular1, TexCoords));
return (ambient + diffuse + specular);
}
// calculates the color when using a point light.
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
// combine results
vec3 ambient = light.ambient * vec3(texture(material.texture_diffuse1, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse1, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.texture_specular1, TexCoords));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return (ambient + diffuse + specular);
}
// calculates the color when using a spot light.
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
// spotlight intensity
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
// combine results
vec3 ambient = light.ambient * vec3(texture(material.texture_diffuse1, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse1, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.texture_specular1, TexCoords));
ambient *= attenuation * intensity;
diffuse *= attenuation * intensity;
specular *= attenuation * intensity;
return (ambient + diffuse + specular);
}

View File

@ -1,19 +1,228 @@
#include"lightCaster.h"
ShaderProgram* lastShader = NULL;
queue<int> available = queue<int>();
Illuminant::Illuminant(){
_position = glm::vec3(0.0f);
_color = glm::vec3(1.0f);
Logger::debug("We do not recommend to construct illuminant without parameter");
}
Illuminant::Illuminant(glm::vec3 position, glm::vec3 color) {
// white color by default
Illuminant::Illuminant(glm::vec3 position, LightType lightType){
_position = position;
_color = color;
setType(lightType);
}
void Illuminant::setPosition(glm::vec3 position) {
// set up with one color
Illuminant::Illuminant(glm::vec3 position, glm::vec3 color, LightType lightType){
_position = position;
_ambient = color * 0.05f;
_diffuse = color * 0.8f;
_specular = color;
setType(lightType);
}
//set up by assign all colors
Illuminant::Illuminant(glm::vec3 position, glm::vec3 ambient,
glm::vec3 diffuse, glm::vec3 specular, LightType lightType){
_position = position;
_ambient = ambient;
_diffuse = diffuse;
_specular = specular;
setType(lightType);
}
// set up with one color建议平行光源使用这个
Illuminant::Illuminant(LightType lightType, glm::vec3 direction, glm::vec3 color) {
_direction = direction;
_ambient = color * 0.05f;
_diffuse = color * 0.8f;
_specular = color;
setType(lightType);
}
// set up with one color建议聚光灯光源使用这个
Illuminant::Illuminant(glm::vec3 position, glm::vec3 direction, glm::vec3 color, LightType lightType) {
_direction = direction;
_position = position;
_ambient = color * 0.05f;
_diffuse = color * 0.8f;
_specular = color;
setType(lightType);
}
Illuminant::~Illuminant() {
switchOff();
if (_lightType == point) {
available.push(this->pointID);
}
}
void Illuminant::setAttenuation(float constant, float linear, float quadratic){
_constant = constant;
_linear = linear;
_quadratic = quadratic;
}
glm::vec3 Illuminant::direction(){
return _direction;
}
glm::vec3 Illuminant::position(){
return _position;
}
glm::vec3 Illuminant::ambient(){
return _ambient;
}
glm::vec3 Illuminant::diffuse(){
return _diffuse;
}
glm::vec3 Illuminant::specular(){
return _specular;
}
Illuminant::LightType Illuminant::type(){
return _lightType;
}
void Illuminant::move(glm::vec3 deltaPos){
_position += deltaPos;
}
void Illuminant::setPosition(glm::vec3 Pos){
_position = Pos;
}
void Illuminant::setColor(glm::vec3 ambient, glm::vec3 diffuse, glm::vec3 specular){
_ambient = ambient;
_diffuse = diffuse;
_specular = specular;
}
// 使用默认的分配系数
void Illuminant::setColor(glm::vec3 color){
_color = color;
_ambient = color * 0.05f;
_diffuse = color * 0.8f;
_specular = color;
}
void Illuminant::setDirection(glm::vec3 direction) {
_direction = direction;
}
void Illuminant::setType(LightType type){
if (available.size() == 0 and type == point) {
Logger::error("Point light number exceed!\n");
return;
}
_lightType = type;
if (type == point) {
pointID = available.front();
available.pop();
}
}
void Illuminant::updateLight(ShaderProgram& shader) {
if (_lightType == dir) {
// directional light
shader.setUniform("dirLight.direction", _direction);
shader.setUniform("dirLight.ambient", _ambient);
shader.setUniform("dirLight.diffuse", _diffuse);
shader.setUniform("dirLight.specular",_specular);
}
else if (_lightType == point)
{ // point light 1
string prefix = "pointLights[" + std::to_string(pointID) + "].";
shader.setUniform(prefix+"position", _position);
shader.setUniform(prefix + "ambient", _ambient);
shader.setUniform(prefix + "diffuse", _diffuse);
shader.setUniform(prefix + "specular", _specular);
shader.setUniform(prefix + "constant",_constant);
shader.setUniform(prefix + "linear", _linear);
shader.setUniform(prefix + "quadratic", _quadratic);
}
else {
// spotLight
shader.setUniform("spotLight.position", _position);
shader.setUniform("spotLight.direction", _direction);
shader.setUniform("spotLight.ambient", _ambient);
shader.setUniform("spotLight.diffuse", _diffuse);
shader.setUniform("spotLight.specular", _specular);
shader.setUniform("spotLight.constant", _constant);
shader.setUniform("spotLight.linear", _linear);
shader.setUniform("spotLight.quadratic", _quadratic);
shader.setUniform("spotLight.cutOff", glm::cos(glm::radians(12.5f)));
shader.setUniform("spotLight.outerCutOff", glm::cos(glm::radians(15.0f)));
}
}
void Illuminant::switchOff() {
// 只要没有颜色就行了
setColor(glm::vec3(0.0f, 0.0f, 0.0f));
if (lastShader != NULL) {
updateLight(*lastShader);
}
}
void init_queue() {
for (int i = 0; i < Illuminant::MAXPOINTLIGHT; i++) {
available.push(i);
Logger::info("23533423q543");
}
}
double r = 1;
// 初始设置所有变量
void setAllLigntUniform(ShaderProgram& shader) {
r = r + 1;
double rr = sin(r / 20)*8;
shader.setUniform("dirLight.direction",0,1,0);
shader.setUniform("dirLight.ambient", 0.0f, 0.0f, 0.0f);
shader.setUniform("dirLight.diffuse", 0.0f, 100.0f, 220.0f);
shader.setUniform("dirLight.specular", 00.0f, 0.0f, 0.0f);
// point light 1
shader.setUniform("pointLights[0].position", 0, 0, 0);
shader.setUniform("pointLights[0].ambient", 0.0f, 0.0f, 0.0f);
shader.setUniform("pointLights[0].diffuse", 0.0f, 0.0f, 0.0f);
shader.setUniform("pointLights[0].specular", 0.0f, 0.0f, 0.0f);
shader.setUniform("pointLights[0].constant", 1.0f);
shader.setUniform("pointLights[0].linear", 0.09f);
shader.setUniform("pointLights[0].quadratic", 0.032f);
// point light 2
shader.setUniform("pointLights[1].position", 0.0f, 0.0f, 0.0f);
shader.setUniform("pointLights[1].ambient", 0.0f, 0.0f, 0.0f);
shader.setUniform("pointLights[1].diffuse", 0.0f, 0.0f, 0.0f);
shader.setUniform("pointLights[1].specular", 0.0f, 0.0f, 0.0f);
shader.setUniform("pointLights[1].constant", 1.0f);
shader.setUniform("pointLights[1].linear", 0.09f);
shader.setUniform("pointLights[1].quadratic", 0.032f);
// point light 3
shader.setUniform("pointLights[2].position", 0.0f, 0.0f, 0.0f);
shader.setUniform("pointLights[2].ambient", 0.0f, 0.0f, 0.0f);
shader.setUniform("pointLights[2].diffuse", 0.0f, 0.0f, 0.0f);
shader.setUniform("pointLights[2].specular", 0.0f, 0.0f, 0.0f);
shader.setUniform("pointLights[2].constant", 1.0f);
shader.setUniform("pointLights[2].linear", 0.09f);
shader.setUniform("pointLights[2].quadratic", 0.032f);
// point light 4
shader.setUniform("pointLights[3].position", 0.0f, 0.0f, 0.0f);
shader.setUniform("pointLights[3].ambient", 0.0f, 0.0f, 0.0f);
shader.setUniform("pointLights[3].diffuse", 0.0f, 0.0f, 0.0f);
shader.setUniform("pointLights[3].specular", 0.0f, 0.0f, 0.0f);
shader.setUniform("pointLights[3].constant", 1.0f);
shader.setUniform("pointLights[3].linear", 0.09f);
shader.setUniform("pointLights[3].quadratic", 0.032f);
// spotLight
shader.setUniform("spotLight.position", 0.0f, 0.0f, 3.0f);
shader.setUniform("spotLight.direction", -0.0f,-0.0f, -1.0f);
shader.setUniform("spotLight.ambient", 0.0f, 0.0f, 0.0f);
shader.setUniform("spotLight.diffuse", 0.0f, 0.0f, 0.0f);
shader.setUniform("spotLight.specular", 0.0f, 0.0f, 0.0f);
shader.setUniform("spotLight.constant", 1.0f);
shader.setUniform("spotLight.linear", 0.09f);
shader.setUniform("spotLight.quadratic", 0.032f);
shader.setUniform("spotLight.cutOff", glm::cos(glm::radians(12.5f)));
shader.setUniform("spotLight.outerCutOff", glm::cos(glm::radians(15.0f)));
}

View File

@ -1,27 +1,86 @@
#pragma once
#include"shader.h"
#include<GLM/glm.hpp>
#include<string>
#include"logger.h"
#include<queue>
using std::queue;
using std::string;
// 发光物不需要纹理所以说需要另外的shader
// 在sceneviewer中被包含
class Illuminant {
private:
glm::vec3 _position;
glm::vec3 _color;
public:
enum LightType { dir, spot, point };
int pointID = -1;
private:
LightType _lightType = dir;
glm::vec3 _direction = glm::vec3(0,2,-1);
glm::vec3 _position = glm::vec3(0.0f);
glm::vec3 _ambient = glm::vec3(0.05f, 0.05f, 0.05f);
glm::vec3 _diffuse = glm::vec3(0.8f, 0.8f, 0.8f);
glm::vec3 _specular = glm::vec3(0.8f, 0.8f, 0.8f);
float _constant = 1.0f;
float _linear = 0.09f;
float _quadratic = 0.032f;
public:
// 修改此处必须同步修改fragment shader的数组定义语句目前此值最大为4
const static int MAXPOINTLIGHT = 4;
Illuminant();
Illuminant(glm::vec3 position, glm::vec3 color);
// white color by default
Illuminant(glm::vec3 position, LightType lightType);
// set up with one color建议点光源使用这个
Illuminant(glm::vec3 position,glm::vec3 color, LightType lightType);
inline glm::vec3 position();
glm::vec3 color();
// set up with one color建议平行光源使用这个
Illuminant(LightType lightType,glm::vec3 direction, glm::vec3 color);
void setPosition(glm::vec3 position);
// set up with one color建议聚光灯光源使用这个
Illuminant(glm::vec3 position, glm::vec3 direction,glm::vec3 color, LightType lightType);
//set up by assign all colors
Illuminant(glm::vec3 position, glm::vec3 ambient, glm::vec3 diffuse, glm::vec3 specular, LightType lightType);
// 析构函数中,如果是点光源,应该增加可用点光源数目。不过暂时没有实现,在上层进行控制
// 无论如何,将此函数置为黑色
~Illuminant();
void setAttenuation(float constant, float linear, float quadratic);
glm::vec3 direction();
glm::vec3 position();
glm::vec3 ambient();
glm::vec3 diffuse();
glm::vec3 specular();
LightType type();
void move(glm::vec3 deltaPos);
void setPosition(glm::vec3 Pos);
// 平行光与手电筒必须设置此项
void setDirection(glm::vec3 direction);
void setColor(glm::vec3 ambient, glm::vec3 diffuse, glm::vec3 specular);
// 使用默认的分配系数
void setColor(glm::vec3 color);
// 将本光源的信息传递给着色器
void updateLight(ShaderProgram& shader);
private:
// 只能在最初设定光源类型,没有必要在期间修改
void setType(LightType type);
// 懒惰删除
void switchOff();
};
inline glm::vec3 Illuminant::position() {
return _position;
}
inline glm::vec3 Illuminant::color() {
return _color;
}
// 初始设置所有变量
void setAllLigntUniform(ShaderProgram& lightingShader);
void init_queue();

View File

@ -22,6 +22,7 @@ Mesh::Mesh(const std::vector<Vertex>& vertices, const std::vector<Texture>& text
void Mesh::render(const ShaderProgram& shader) const {
unsigned int diffuseNr = 1;
unsigned int specularNr = 1;
shader.setUniform("material.shininess",_shininess);
for (int i = 0; i < _textures.size(); i++) {
OPENGL_EXTRA_FUNCTIONS->glActiveTexture(GL_TEXTURE0 + i); // activate proper texture unit before binding
// retrieve texture number (the N in diffuse_textureN)

View File

@ -14,7 +14,7 @@ private:
std::vector<Texture> _textures;
// we can control shininess in mesh
float _shininess = 64.0f;
float _shininess = 32.0f;
VertexArrayObject _vao = VertexArrayObject::empty();

View File

@ -78,6 +78,12 @@ void SceneViewer::initializeGL() {
vertexShader.dispose();
fragmentShader.dispose();
// 进行光照初始化
setAllLigntUniform(_shaderProgram);
init_queue();
// 设置光照
Model* backpackModel = new Model("D:\\code\\ComputerGraphic\\backpack\\backpack.obj");
Logger::info("Model loaded");
Renderable backpack(backpackModel);
@ -190,16 +196,20 @@ void SceneViewer::wheelEvent(QWheelEvent* event) {
void SceneViewer::update_light() {
// 对于发光体,
//model is in Illuminate
// view is from camera
// projection is from caller
_shaderProgram.setUniform("lightPos",_illuminants[0].position());
_shaderProgram.setUniform("lightColor", _illuminants[0].color());
_shaderProgram.setUniform("viewPos", _camera.position());
// 要给着色器传递viewPos
setAllLigntUniform(_shaderProgram);
for (int i = 0; i < _illuminants.size(); i++) {
_illuminants[i].updateLight(_shaderProgram);
}
}
void SceneViewer::addDirLight(glm::vec3 direction, glm::vec3 color) {
_illuminants.push_back(Illuminant(Illuminant::LightType::dir, direction,color));
}
void SceneViewer::addPointLight(glm::vec3 position, glm::vec3 color) {
_illuminants.push_back(Illuminant(position, color, Illuminant::LightType::point));
}
void SceneViewer::addSpotLight(glm::vec3 direction, glm::vec3 position, glm::vec3 color) {
_illuminants.push_back(Illuminant(position,direction, color, Illuminant::LightType::spot));
}

View File

@ -45,6 +45,9 @@ public:
SceneViewer(QWidget* parent = 0);
~SceneViewer();
void update_light();
void addDirLight(glm::vec3 direction, glm::vec3 color);
void addPointLight(glm::vec3 position, glm::vec3 color);
void addSpotLight(glm::vec3 direction,glm::vec3 position, glm::vec3 color);
protected:
// OpenGL functions

View File

@ -15,7 +15,7 @@ void main()
{
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
gl_Position = projection * view * vec4(FragPos, 1.0);
}