文章目录

  • 初始代码
  • 练习一
  • 练习二
  • 练习三
  • 练习四

初始代码

l i g h t s h a d e r : light\ shader: light shader:

#version 330 core
layout (location = 0) in vec3 aPos;uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;void main()
{gl_Position = projection * view * model * vec4(aPos,1.0);
}
#version 330 core
out vec4 FragColor;void main()
{FragColor = vec4(1.0);  将向量的四个分量全部设置为1.0
}

o b j e c t s h a d e r : object\ shader: object shader:

#version 330 core
layout (location = 0) in vec3 aPos;   // 位置变量的属性位置值为 0
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;uniform mat4 model;   //模型
uniform mat4 view;  //观察
uniform mat4 projection;    //投影out vec3 Normal;
out vec3 FragPos;
out vec2 TexCoords;void main()
{// 注意乘法要从右向左读gl_Position = projection * view * model * vec4(aPos, 1.0);Normal = mat3(transpose(inverse(model))) * aNormal;FragPos = vec3(model * vec4(aPos, 1.0));TexCoords = aTexCoords;
}
#version 330 corestruct Material
{sampler2D diffuse;sampler2D specular;float shininess;
};struct Light
{vec3 position;vec3 ambient;vec3 diffuse;vec3 specular;
};in vec3 Normal;
in vec3 FragPos;
in vec2 TexCoords;out vec4 FragColor;  uniform Material material;
uniform Light light;
uniform vec3 viewPos;void main()
{//环境光vec3 ambient = light.ambient * vec3(texture(material.diffuse,TexCoords));//漫反射vec3 norm = normalize(Normal);vec3 lightDir = normalize(light.position - FragPos);float diff = max(dot(norm,lightDir),0.0);vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse,TexCoords));//镜面反射vec3 viewDir = normalize(viewPos - FragPos);vec3 reflectDir = reflect(-lightDir,norm);float spec = pow(max(dot(reflectDir,viewDir),0.0),material.shininess);vec3 specular = light.specular * spec * vec3(texture(material.specular,TexCoords));//最终结果vec3 result = ambient + diffuse + specular;FragColor = vec4(result,1.0);
}

c p p : cpp: cpp:

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include "shader.h"
#include "stb_image.h"
#include "camera.h"
#include "texture.h"
using std::cout;//窗口回调函数
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{//绘图视口 3D坐标到2D坐标的转换(映射)和这些参数(宽高)有关glViewport(0, 0, width, height);
}//键盘回调
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);//鼠标回调
void mouse_callback(GLFWwindow* window, double xpos, double ypos);//滚轮回调
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);//窗口初始大小
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;//物体着色器
const char* vShaderPath = "ShaderFiles/shader.vert";
const char* fShaderPath = "ShaderFiles/shader.frag";
//光源着色器
const char* lightvShaderPath = "ShaderFiles/light_shader.vert";
const char* lightfShaderPath = "ShaderFiles/light_shader.frag";//混合颜色的插值
float mixValue = 0.2f;
//记录鼠标坐标
float lastX, lastY;
bool firstMouse = true;//摄像机
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));//光源位置
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);int main()
{//glfw初始化glfwInit();//告诉glfw我们所使用的opengl版本 此处为3.3glfwWindowHint(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){cout << "Failed to create GLFW window\n";glfwTerminate();return -1;}glfwMakeContextCurrent(window);glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);//设置窗口回调函数glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);//键盘回调函数glfwSetKeyCallback(window, key_callback);//鼠标回调glfwSetCursorPosCallback(window, mouse_callback);//滚轮回调glfwSetScrollCallback(window, scroll_callback);if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){cout << "Failed to initialize GLAD\n";return -1;}//开启深度测试glEnable(GL_DEPTH_TEST);//着色器对象Shader shaderProgram = Shader(vShaderPath, fShaderPath);Shader lightShaderProgram = Shader(lightvShaderPath, lightfShaderPath);float vertices[] = {// positions          // normals           // texture coords-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 0.0f,0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 0.0f,0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 1.0f,0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 1.0f,-0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 1.0f,-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 0.0f,-0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   0.0f, 0.0f,0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   1.0f, 0.0f,0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   1.0f, 1.0f,0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   1.0f, 1.0f,-0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   0.0f, 1.0f,-0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   0.0f, 0.0f,-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f, 0.0f,-0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  1.0f, 1.0f,-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f, 1.0f,-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f, 1.0f,-0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  0.0f, 0.0f,-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f, 0.0f,0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f, 0.0f,0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  1.0f, 1.0f,0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f, 1.0f,0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f, 1.0f,0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  0.0f, 0.0f,0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f, 0.0f,-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f, 1.0f,0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  1.0f, 1.0f,0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f, 0.0f,0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f, 0.0f,-0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  0.0f, 0.0f,-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f, 1.0f,-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 1.0f,0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 1.0f,0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 0.0f,0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 0.0f,-0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 0.0f,-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 1.0f};//顶点缓冲对象 VBO//顶点数组对象 VAOunsigned int VBO, VAO;//渲染物体glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//设置顶点属性glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));glEnableVertexAttribArray(1);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));glEnableVertexAttribArray(2);//光源unsigned int lightVAO;glGenVertexArrays(1, &lightVAO);glBindVertexArray(lightVAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);//漫反射贴图Texture diffuseTexture("diffuseTexture", "Images/container2_diffuse.png");//镜面光贴图//Texture specularTexture("specuTexture", "Images/container2_specular.png");Texture specularTexture("specuTexture", "Images/lighting_maps_specular_color.png");//线框模式//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//这些uniform不会更新 可以放到循环外面shaderProgram.use();shaderProgram.setInt("material.diffuse", diffuseTexture.getTextureUnitID());shaderProgram.setInt("material.specular", specularTexture.getTextureUnitID());shaderProgram.setFloat("material.shininess", 64.0f);shaderProgram.setVec3("light.ambient", 0.2f, 0.2f, 0.2f);shaderProgram.setVec3("light.diffuse", 0.5f, 0.5f, 0.5f);shaderProgram.setVec3("light.specular", 1.0f, 1.0f, 1.0f);shaderProgram.setVec3("light.position", lightPos);while (!glfwWindowShouldClose(window)){glClearColor(0.1f, 0.1f, 0.1f, 0.1f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//矩阵运算glm::mat4 lightModel(1.0f);glm::mat4 view = camera.GetViewMatrix();glm::mat4 projection = glm::perspective(glm::radians(camera.Fov), SCR_WIDTH * 1.0f / SCR_HEIGHT, 0.1f, 100.0f);//激活着色器shaderProgram.use();shaderProgram.setVec3("viewPos", camera.Position);shaderProgram.setMat4("model", lightModel);shaderProgram.setMat4("view", view);shaderProgram.setMat4("projection", projection);//贴图diffuseTexture.use();specularTexture.use();glBindVertexArray(VAO);glDrawArrays(GL_TRIANGLES, 0, 36);//光源着色器lightShaderProgram.use();lightModel = glm::translate(lightModel, lightPos);lightModel = glm::scale(lightModel, glm::vec3(0.2f));lightShaderProgram.setMat4("model", lightModel);lightShaderProgram.setMat4("view", view);lightShaderProgram.setMat4("projection", projection);glBindVertexArray(lightVAO);glDrawArrays(GL_TRIANGLES, 0, 36);glfwSwapBuffers(window);glfwPollEvents();}//这一步是可选的glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);//glDeleteBuffers(1, &EBO);//释放资源glfwTerminate();return 0;
}void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{if (action == GLFW_REPEAT || action == GLFW_PRESS){if (key == GLFW_KEY_ESCAPE){glfwSetWindowShouldClose(window, GL_TRUE);return;}switch (key){case GLFW_KEY_UP:mixValue += 0.1f;if (mixValue >= 1.0f)mixValue = 1.0f;break;case GLFW_KEY_DOWN:mixValue -= 0.1f;if (mixValue <= 0.0f)mixValue = 0.0f;break;case GLFW_KEY_W:camera.ProcessKeyboard(FORWARD);break;case GLFW_KEY_S:camera.ProcessKeyboard(BACKWARD);break;case GLFW_KEY_A:camera.ProcessKeyboard(LEFT);break;case GLFW_KEY_D:camera.ProcessKeyboard(RIGHT);break;default:break;}}
}void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{if (firstMouse){firstMouse = false;lastX = xpos, lastY = ypos;}camera.ProcessMouseMovement(xpos - lastX, lastY - ypos);lastX = xpos;lastY = ypos;
}void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{camera.ProcessMouseScroll(yoffset);
}

注:若要查看封装的类的代码,请看我的其他博客。

练习一

调整光源的环境光、漫反射和镜面光向量,看看它们如何影响箱子的视觉输出。

shaderProgram.setVec3("light.ambient", 0.2f, 0.2f, 0.2f);
shaderProgram.setVec3("light.diffuse", 0.5f, 0.5f, 0.5f);
shaderProgram.setVec3("light.specular", 1.0f, 1.0f, 1.0f);

增大环境光。

shaderProgram.setVec3("light.ambient", 1.0f, 1.0f, 1.0f);
shaderProgram.setVec3("light.diffuse", 0.5f, 0.5f, 0.5f);
shaderProgram.setVec3("light.specular", 1.0f, 1.0f, 1.0f);

增大漫反射光。

shaderProgram.setVec3("light.ambient", 0.2f, 0.2f, 0.2f);
shaderProgram.setVec3("light.diffuse", 1.0f, 1.0f, 1.0f);
shaderProgram.setVec3("light.specular", 1.0f, 1.0f, 1.0f);

增大镜面反射光。

shaderProgram.setVec3("light.ambient", 0.2f, 0.2f, 0.2f);
shaderProgram.setVec3("light.diffuse", 0.5f, 0.5f, 0.5f);
shaderProgram.setVec3("light.specular", 3.0f, 3.0f, 3.0f);

练习二

尝试在片段着色器中反转镜面光贴图的颜色值,让木头显示镜面高光而钢制边缘不反光(由于钢制边缘中有一些裂缝,边缘仍会显示一些镜面高光,虽然强度会小很多)。

修改object的片段着色器即可:

#version 330 corestruct Material
{sampler2D diffuse;sampler2D specular;float shininess;
};struct Light
{vec3 position;vec3 ambient;vec3 diffuse;vec3 specular;
};in vec3 Normal;
in vec3 FragPos;
in vec2 TexCoords;out vec4 FragColor;  uniform Material material;
uniform Light light;
uniform vec3 viewPos;void main()
{//环境光vec3 ambient = light.ambient * vec3(texture(material.diffuse,TexCoords));//漫反射vec3 norm = normalize(Normal);vec3 lightDir = normalize(light.position - FragPos);float diff = max(dot(norm,lightDir),0.0);vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse,TexCoords));//镜面反射vec3 viewDir = normalize(viewPos - FragPos);vec3 reflectDir = reflect(-lightDir,norm);float spec = pow(max(dot(reflectDir,viewDir),0.0),material.shininess);//vec3 specular = light.specular * spec * vec3(texture(material.specular,TexCoords));vec3 specular = light.specular * spec * (vec3(1.0) - vec3(texture(material.specular,TexCoords)));//最终结果vec3 result = ambient + diffuse + specular;FragColor = vec4(result,1.0);
}

练习三

使用漫反射贴图创建一个彩色而不是黑白的镜面光贴图,看看结果看起来并不是那么真实了。如果你不会生成的话,可以使用这张彩色的镜面光贴图。

//镜面光贴图
//Texture specularTexture("specuTexture", "Images/container2_specular.png");
Texture specularTexture("specuTexture", "Images/lighting_maps_specular_color.png");


练习四

添加一个叫做放射光贴图(Emission Map)的东西,它是一个储存了每个片段的发光值(Emission Value)的贴图。发光值是一个包含(假设)光源的物体发光(Emit)时可能显现的颜色,这样的话物体就能够忽略光照条件进行发光(Glow)。游戏中某个物体在发光的时候,你通常看到的就是放射光贴图(比如 机器人的眼,或是箱子上的灯带)。将这个纹理(作者为 creativesam)作为放射光贴图添加到箱子上,产生这些字母都在发光的效果。


首先修改object的片段着色器:

#version 330 corestruct Material
{sampler2D diffuse;sampler2D specular;float shininess;
};struct Light
{vec3 position;vec3 ambient;vec3 diffuse;vec3 specular;
};in vec3 Normal;
in vec3 FragPos;
in vec2 TexCoords;out vec4 FragColor;  uniform Material material;
uniform Light light;
uniform vec3 viewPos;
uniform sampler2D EmissionMap;void main()
{//环境光vec3 ambient = light.ambient * vec3(texture(material.diffuse,TexCoords));//漫反射vec3 norm = normalize(Normal);vec3 lightDir = normalize(light.position - FragPos);float diff = max(dot(norm,lightDir),0.0);vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse,TexCoords));//镜面反射vec3 viewDir = normalize(viewPos - FragPos);vec3 reflectDir = reflect(-lightDir,norm);float spec = pow(max(dot(reflectDir,viewDir),0.0),material.shininess);vec3 specular = light.specular * spec * vec3(texture(material.specular,TexCoords));//放射光vec3 emission = texture(EmissionMap,TexCoords).xyz;//最终结果vec3 result = ambient + diffuse + specular + emission;FragColor = vec4(result,1.0);
}

然后在main.cpp中修改以下几处代码:

//放射光贴图
Texture emissionTexture("emissionTexture", "Images/emission_map.jpg");
……
shaderProgram.setInt("EmissionMap", emissionTexture.getTextureUnitID());
……
emissionTexture.use();

其实就是多了一个放射光嘛。

LearnOpenGL 光照—光照贴图—练习(放射光贴图)相关推荐

  1. 波特图的零点极点-最后一部分电阻并电容的波特图-运放的波特图

    从放大器失调电压.偏置电流.共模抑制比,电源抑制比到开环增益,在直流或者低频率范围内,影响放大器信号调理的参数已经介绍完成.期间没有单独介绍基础理论,默认诸位工程师已经掌握同相.反相等基础放大电路,& ...

  2. LearnOpenGL 光照—光照贴图

    文章目录 写在前面 光照贴图 漫反射贴图 镜面光贴图 采样镜面光贴图 总结 写在前面 原文链接.原文应该是github上的一个项目,本文主要用来记录一些知识点和自己遇到的问题. 光照贴图 在上一节中, ...

  3. Opengl-光照-基本光照-光照贴图(现在告别单调的方块弄个箱子)

    前言 前面我们跟着LearnOpengl学习的都是通过怎么定义一些顶点数据弄出一个立方体在三维世界里模拟光照模拟光源.看着是有点真实的样子了..可是你见过哪个真实世界里都是这些个立方体的,肯定都是真切 ...

  4. opengl高级光照之视差贴图(陡峭视差贴图以及视差遮蔽映射)

    视差贴图 视差贴图官方文档 视差贴图 视差贴图(Parallax Mapping)技术和法线贴图差不多,但它有着不同的原则.和法线贴图一样视差贴图能够极大提升表面细节,使之具有深度感.它也是利用了视错 ...

  5. gif分解工具_Python之GIF图倒放,沙雕快乐源泉

    GIF图现在已经融入了我们的日常网络生活,微信群.QQ群.朋友圈......一言不合就斗图,你怕了吗? 不用担心,只要学会了Python之GIF倒放技能,你就是"斗图王". 咱们直 ...

  6. python导入gif_Python之GIF图倒放,沙雕快乐源泉!我已经笑了一天了!

    GIF图现在已经融入了我们的日常网络生活,微信群.QQ群.朋友圈......一言不合就斗图,你怕了吗? 不用担心,只要学会了Python之GIF倒放技能,你就是"斗图王". 咱们直 ...

  7. android帧动画倒放,GIF动态图怎么倒放_倒放GIF动态图的简单方法介绍_3DM手游

    GIF动态图怎么倒放?应该有很多网友都想知道吧,看了很多视频倒放的,那么GIF倒放要怎么完成呢?其实方法很简单,不会的网友们,下面就跟着3DM手游网小编一起来看看吧,帮助你快速学会GIF动态图倒放的方 ...

  8. 运放补偿网络波特图LTspice仿真:PI、II型、PID

    运放补偿网络波特图LTspice仿真:PI.II型.PID 偏置调节电路 补偿器的输出电压只有在一定的范围内时才能正常工作.开环工作时,补偿器的输出很容易饱和,导致仿真结果不正确. 所以,需要加一个偏 ...

  9. 怎样将gif动图倒放?教你一键快速倒放gif动图

    当我们看到一些有趣的gif动图,突发奇想想要把这些gif动图画面倒放,生成更有趣的gif动画图片时,gif图怎么倒放呢?给大家分享一款gif动画在线制作工具(https://www.gif.cn/)- ...

最新文章

  1. tddebug怎么读取asm文件_如何利用 ASM 实现既有方法的增强?
  2. python 正则search 所有_python之路----正则re(search,match,findall……)
  3. 宝塔apache mysql_商淘多商户商城系统部署之宝塔面板(Nginx/Apache+MySQL+PHP7.1)
  4. 前缀和与差分的使用(新手快速入门)
  5. 【机器视觉】 fuzzy_measure_pairs算子
  6. 控制台下修改系统驱动状态的代码
  7. LeetCode 646. 最长数对链
  8. 软件测试工程师-缺陷报告
  9. python替换缺失值,处理空值+生成图形+图形标准化
  10. Error creating bean with name 'dataSource' defined in class path resource [spring/spring-dao.xml]:
  11. window自动备件软件
  12. VBA基础知识———常用语句
  13. mysql coreseek_Coreseek使用
  14. PS精讲精练读书笔记
  15. 如何设置excel回车换行
  16. HTML5开发 页游/手游动画及游戏系列教程(Game Tutorial):(一)物体动起来吧
  17. [Hgame CTF]easyenc
  18. 如何用JAVA制作一个漂亮的表格
  19. 愿码(ChainDesk.CN):CoinBase Pro增加了对xrp的支持
  20. php格式用什么能打开,文件格式为.php的文件用什么软件打开?

热门文章

  1. 普通人可以自己直接制作APP吗?自己能做好App吗?
  2. vivo X21屏幕指纹版评测:惊艳的不止是外观,还有体验
  3. 周大福周周好珠宝丨以爱之名,宠我万千
  4. [Win32SDK基本] 窗口详解(超详细)
  5. mysql修改、增加、删除字段名等命令
  6. jquery 回到顶部动画
  7. QQ上怎样快速查找群里面想要的群文件(在电脑上)
  8. java 时间戳转php_java时间戳转php时间戳_后端开发
  9. 华为鸿蒙细节,华为鸿蒙内测细节曝光 五大细节与安卓明显不同
  10. Python 机器学习框架