Blinn-Phong光照

1|0颜色

颜色是由光的颜色乘物品的颜色得到的
光的颜色值不是比例,如果值大就亮,值小就暗。比如(1.0f, 1.0f, 1.0f)就比(0.2f, 0.2f, 0.2f)亮

fragmentshader

#version 330 core out vec4 fragColor; uniform vec3 lightcolor, objectcolor; void main() { fragColor = vec4(lightcolor * objectcolor, 1.0f); }

在main函数里,先定位location,再use那个program,然后再改uniform的值

unsigned int lightLoc = glGetUniformLocation(Cubeshader.ID, "lightcolor"); unsigned int objectLoc = glGetUniformLocation(Cubeshader.ID, "objectcolor"); Cubeshader.use(); glUniform3f(lightLoc, 1.0f, 1.0f, 1.0f); glUniform3f(objectLoc, 0.5f, 1.0f, 0.4f);

或者在Shader函数里定义修改Uniform的方法:

void setMat4(const std::string &name, const glm::mat4 &mat) { glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, glm::value_ptr(mat)); } void setvec3(const std::string &name, const glm::vec3 &vec) { glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, glm::value_ptr(vec)); } void setvec3(const std::string &name, float x, float y, float z) const { glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z); }

main.cpp

Cubeshader.use(); Cubeshader.setvec3("lightcolor", 1.0f, 1.0f, 1.0f); Cubeshader.setvec3("objectcolor", 0.5f, 1.0f, 0.4f);

然后VAO只记录了glBindBuffer绑定了的VBO的glVertexAttribPointer和glEnableVertexAttribArray的值,在使用这个着色器前需要先shader.use(),然后再改这个shader的uniform值

lightshader.use(); glm::mat4 model(1.0f); model = glm::translate(model, lightPos); view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp); projection = glm::perspective(glm::radians(45.0f), (float)800 / (float)600, 0.1f, 100.0f); lightshader.setMat4("model", model); lightshader.setMat4("view", view); lightshader.setMat4("projection", projection); glBindVertexArray(lightVAO); glDrawArrays(GL_TRIANGLES, 0, 36);

2|0光照

2|1漫反射diffuse

获得每个点的法向量,写在vertices属性里,光照不用法向量属性,物体用

glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //第一个是类型,第二个是大小,第三个是数据 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glEnableVertexAttribArray(1);
glBindVertexArray(lightVAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glEnableVertexAttribArray(0);

在顶点着色器里把顶点坐标转化到世界坐标系以备与法向量点积
FragPos = vec3(model * vec4(aPos, 1.0));
然后把法向量进行操作使之与view无关
Normal = mat3(transpose(inverse(model))) * aNormal;
并传到fragment shader里。
标准化的法向量与标准化了的(光源-顶点)做点积,得到cos
然后乘光照,就是这个点获得的光照强度

vec3 norm = normalize(Normal); vec3 lightDir = normalize(lightPos - FragPos); float diff = max(dot(norm, lightDir), 0.0); vec3 diffuse = diff * lightcolor;

2|2镜面反射specular

视线向量(摄像机-物体)点积反射向量(vec3 reflectDir = reflect(-lightDir, norm);)函数,这个0-1之间的值再乘《高光度》次幂,就是高光分量
reflect函数第一个参数必须是光照的方向,需要上面的lightDir取反,第二个是标准化了的法线方向

fragmentshader

uniform viewPos; float specularStrength = 0.5; vec3 ViewDir = normalize(viewPos-FragPos); vec3 reflectDir = reflect(-lightDir, norm); float spec = pow(max(dot(ViewDir, reflectDir),0.0), 32); vec3 specular = specularStrength * spec * lightcolor;

3|0所有程序

#include<glad/glad.h> #include<GLFW/glfw3.h> #include<iostream> #include<Shader.cpp> #define STB_IMAGE_IMPLEMENTATION #include<stb_image.h> #include<glm/glm.hpp> #include<glm/gtc/matrix_transform.hpp> #include<glm/gtc/type_ptr.hpp> glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f); glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f); glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f); void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } void processInput(GLFWwindow* window) { if (glfwGetKey(window, GLFW_KEY_KP_ENTER) == GLFW_PRESS or glfwGetKey(window, GLFW_KEY_ENTER) == GLFW_PRESS or glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); float cameraSpeed = 0.05f; if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) cameraPos += cameraSpeed * cameraFront; if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) cameraPos -= cameraSpeed * cameraFront; if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) cameraPos += cameraSpeed * glm::normalize(glm::cross(cameraUp, cameraFront)); if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) cameraPos -= cameraSpeed * glm::normalize(glm::cross(cameraUp, cameraFront)); } int main() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //创建窗口对象 GLFWwindow* window = glfwCreateWindow(800, 600, "LJHyyds", NULL, NULL); if (window == NULL) { std::cout << "Failed to create" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); //初始化GLAD管理指针,加载系统OpenGL函数指针 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to init GLAD" << std::endl; return -1; } glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); Shader Cubeshader("shader.vs", "shader.fs"); Shader lightshader("shader.vs", "lightshader.fs"); 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 }; 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) }; unsigned int VBO, VAO, lightVAO; glGenBuffers(1, &VBO); glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //第一个是类型,第二个是大小,第三个是数据 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); glEnable(GL_DEPTH_TEST); glGenVertexArrays(1, &lightVAO); glBindVertexArray(lightVAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glm::vec3 lightPos(0.2f, 0.5f, 0.0f); glm::mat4 view = glm::mat4(1.0f), projection = glm::mat4(1.0f); while (!glfwWindowShouldClose(window)) { processInput(window); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); Cubeshader.use(); Cubeshader.setvec3("lightcolor", 1.0f, 1.0f, 1.0f); Cubeshader.setvec3("objectcolor", 0.5f, 1.0f, 0.4f); Cubeshader.setvec3("lightPos", 0.2f, 0.5f, 0.0f); Cubeshader.setvec3("viewPos", cameraPos); for (unsigned int i = 0; i < 10; i++) { glm::mat4 model = glm::mat4(1.0f); model = glm::translate(model, cubePositions[i]); model = glm::rotate(model, glm::radians(20.0f*i), glm::vec3(1.0f, 0.2f, 0.3f)); view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp); projection = glm::perspective(glm::radians(45.0f), (float)800 / (float)600, 0.1f, 100.0f); Cubeshader.setMat4("model", model); Cubeshader.setMat4("view", view); Cubeshader.setMat4("projection", projection); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 36); } lightshader.use(); glm::mat4 model(1.0f); model = glm::translate(model, lightPos); view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp); projection = glm::perspective(glm::radians(45.0f), (float)800 / (float)600, 0.1f, 100.0f); lightshader.setMat4("model", model); lightshader.setMat4("view", view); lightshader.setMat4("projection", projection); glBindVertexArray(lightVAO); glDrawArrays(GL_TRIANGLES, 0, 36); glfwSwapBuffers(window); glfwPollEvents(); } glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); //关闭窗口 glfwTerminate(); return 0; }

vertexshader

#version 330 core layout (location=0) in vec3 aPos; layout (location=1) in vec3 aNormal; uniform mat4 transform, model, view, projection; out vec3 Normal, FragPos; void main() { gl_Position = projection * view * model * vec4(aPos, 1.0); FragPos = vec3(model * vec4(aPos, 1.0)); Normal = mat3(transpose(inverse(model))) * aNormal; }

fragment shader

#version 330 core out vec4 fragColor; in vec3 Normal, FragPos; uniform vec3 lightcolor, objectcolor, lightPos, viewPos; void main() { float ambientstrength = 0.1; vec3 ambient = ambientstrength * lightcolor; vec3 norm = normalize(Normal); vec3 lightDir = normalize(lightPos - FragPos); float diff = max(dot(norm, lightDir), 0.0); vec3 diffuse = diff * lightcolor; float specularStrength = 0.5; vec3 ViewDir = normalize(viewPos-FragPos); vec3 reflectDir = reflect(-lightDir, norm); float spec = pow(max(dot(ViewDir, reflectDir),0.0), 32); vec3 specular = specularStrength * spec * lightcolor; vec3 result = (ambient + diffuse + specular) * objectcolor; fragColor = vec4(result, 1.0f); }

shader类

#ifndef SHADER_H #endif SHADER_H #include<glad/glad.h> #include<string> #include<fstream> #include<sstream> #include<iostream> #include<glm/glm.hpp> #include<glm/gtc/matrix_transform.hpp> #include<glm/gtc/type_ptr.hpp> class Shader { public: unsigned int ID; Shader(const char* vertexPath, const char* fragmentPath) { using namespace std; string vertexCode; string fragmentCode; ifstream vShaderFile; ifstream fShaderFile; vShaderFile.exceptions(ifstream::failbit | ifstream::badbit); fShaderFile.exceptions(ifstream::failbit | ifstream::badbit); try { vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); stringstream vShaderStream, fShaderStream; vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); vShaderFile.close(); fShaderFile.close(); vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); } catch (ifstream::failure e) { cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << endl; } const char* vShaderCode = vertexCode.c_str(); const char* fShaderCode = fragmentCode.c_str(); unsigned int vertexShader, fragmentShader; vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vShaderCode, NULL); glCompileShader(vertexShader); int success; char infolog[512]; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertexShader, 512, NULL, infolog); cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infolog << endl; } fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fShaderCode, NULL); glCompileShader(fragmentShader); glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragmentShader, 512, NULL, infolog); cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infolog << endl; } ID = glCreateProgram(); glAttachShader(ID, vertexShader); glAttachShader(ID, fragmentShader); glLinkProgram(ID); glGetProgramiv(ID, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(ID, 512, NULL, infolog); cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infolog << endl; } glDeleteShader(vertexShader); glDeleteShader(fragmentShader); } void use() { glUseProgram(ID); } void setMat4(const std::string &name, const glm::mat4 &mat) { glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, glm::value_ptr(mat)); } void setvec3(const std::string &name, const glm::vec3 &vec) { glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, glm::value_ptr(vec)); } void setvec3(const std::string &name, float x, float y, float z) const { glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z); } };

4|0材质

物体材质:

struct Material { vec3 ambient; vec3 diffuse; vec3 specular; float shininess; }; uniform Material material;

光照参数:

struct Light { vec3 position; vec3 ambient; vec3 diffuse; vec3 specular; }; uniform Light light;

最后的计算就要直接用material的颜色乘光的颜色

void main() { vec3 ambient = light.ambient * material.ambient; vec3 norm = normalize(Normal); vec3 lightDir = normalize(light.position - FragPos); float diff = max(dot(norm, lightDir), 0.0); vec3 diffuse = diff * light.diffuse * material.diffuse; vec3 ViewDir = normalize(viewPos-FragPos); vec3 reflectDir = reflect(-light.position, norm); float spec = pow(max(dot(ViewDir, reflectDir),0.0), material.shininess); vec3 specular = spec * light.specular * material.specular; vec3 result = ambient + diffuse + specular; fragColor = vec4(result, 1.0f); }

fragmentshader

#version 330 core struct Material{ vec3 ambient; vec3 diffuse; vec3 specular; float shininess; }; struct Light { vec3 position; vec3 ambient; vec3 diffuse; vec3 specular; }; uniform Light light; uniform Material material; out vec4 fragColor; in vec3 Normal, FragPos; in vec2 TexCoords; uniform vec3 viewPos; void main() { vec3 ambient = light.ambient * material.ambient; vec3 norm = normalize(Normal); vec3 lightDir = normalize(light.position - FragPos); float diff = max(dot(norm, lightDir), 0.0); vec3 diffuse = diff * light.diffuse * material.diffuse; vec3 ViewDir = normalize(viewPos-FragPos); vec3 reflectDir = reflect(-lightDir, norm); //哭死,之前写成reflect(-light.position, norm)调了一天的bug float spec = pow(max(dot(ViewDir, reflectDir),0.0), material.shininess); vec3 specular = spec * light.specular * material.specular; vec3 result = ambient + diffuse + specular; fragColor = vec4(result, 1.0f); }


如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。

__EOF__

本文作者Liujiahang
本文链接https://www.cnblogs.com/IamIron-Man/p/16616743.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   IamIron-Man  阅读(65)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示