OpenGL_Learn12(光照)

 续OpenGL_Learn11(光照)-CSDN博客

1. 镜面高光

和漫反射光照一样,镜面光照也决定于光的方向向量和物体的法向量,但是它也决定于观察方向,例如玩家是从什么方向看向这个片段的。镜面光照决定于表面的反射特性。

我们通过根据法向量翻折入射光的方向来计算反射向量(对称就是R那条线)。然后我们计算反射向量与观察方向的角度差,它们之间夹角越小,镜面光的作用就越大。由此产生的效果就是,我们看向在入射光在表面的反射方向时,会看到一点高光。

只需要修改

cube.vs

增加翻折后的法向量

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

out vec3 FragPos;
out vec3 Normal;

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

void main()
{
    FragPos=vec3(model*vec4(aPos,1.0));
    Normal=mat3(transpose(inverse(model)))*aNormal;
    gl_Position = projection * view  * vec4(FragPos, 1.0);
}

cube.fs

 增加一个高光因子

#version 330 core
out vec4 FragColor;

in vec3 Normal;
in vec3 FragPos;

uniform vec3 objectColor;
uniform vec3 lightColor;
uniform vec3 lightPos;
uniform vec3 viewPos;

void main()
{
    //ambient
    float ambientStrength=0.1;
    vec3 ambient=ambientStrength*lightColor;

    //diffuse
    vec3 norm=normalize(Normal);
    vec3 lightDir=normalize(lightPos-FragPos);//光的方向向量是光源位置向量与片段位置向量之间的向量差。
    //对norm和lightDir向量进行点乘,计算光源对当前片段实际的漫反射影响
    //两个向量之间的角度越大,漫反射分量就会越小,点乘的几何意义也如此
    float diff=max(dot(norm,lightDir),0.0);
    vec3 diffuse=diff*lightColor;

    //specular
    float specularStrength=0.5;//高光强度
    //漫反射是光源指向片段位置。现在这个是摄像机指向片段位置
    vec3 viewDir=normalize(viewPos-FragPos);
    vec3 reflectDir=reflect(-lightDir,norm);//reflect第一个参数就是要片段指向摄像机位置
    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.0);
}

 main.cpp

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>
#include "stb_image.h"
#include <cmath>
#include "shader.h"
#include "camera.h"

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);

// settings
const unsigned int SCR_WIDTH = 1800;
const unsigned int SCR_HEIGHT = 1200;


//camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
float lastX = SCR_WIDTH / 2.0f;
float lastY = SCR_HEIGHT / 2.0f;
bool firstMouse = true;

//timing
float deltaTime = 0.0f;//不同配置绘制速度不同,所以需要这个属性
float lastFrame = 0.0f;

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

int main() {
	//glfw:initialize and configure
	//=============================
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

	//glfw window creation
	//=============================
	GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Learn", NULL, NULL);
	if (window == NULL) {
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}

	glfwMakeContextCurrent(window);
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
	glfwSetCursorPosCallback(window, mouse_callback);
	glfwSetScrollCallback(window, scroll_callback);

	//tell GLFW to capture our mouse
	glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

	//glad::load all OPenGL function pointers
	//=============================
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}

	//configure gloabl opengl state
	//=============================
	glEnable(GL_DEPTH_TEST);

	//build and compile our shader zprogram
	//=============================
	Shader lightingShader("./cube.vs", "./cube.fs");
    Shader lightingCubeShader("./light_cube.vs", "./light_cube.fs");
	//set up vertex data 

    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
    };

    //第一个
    unsigned int VBO, cubeVAO;
    glGenVertexArrays(1, &cubeVAO);
    glGenBuffers(1, &VBO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindVertexArray(cubeVAO);

    //position attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    //normal attribute
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    
    //第二个
    unsigned int lightCubeVAO;
    glGenVertexArrays(1, &lightCubeVAO);
    glBindVertexArray(lightCubeVAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);



    // render loop
    // -----------
    while (!glfwWindowShouldClose(window))
    {
        // per-frame time logic
        // --------------------
        float currentFrame = static_cast<float>(glfwGetTime());
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        // input
        // -----
        processInput(window);

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

        // be sure to activate shader when setting uniforms/drawing objects
        lightingShader.use();
        lightingShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f);
        lightingShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f);
        lightingShader.setVec3("lightPos", lightPos);
        lightingShader.setVec3("viewPos", camera.Position);

        // view/projection transformations
        glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
        glm::mat4 view = camera.GetViewMatrix();
        lightingShader.setMat4("projection", projection);
        lightingShader.setMat4("view", view);

        // world transformation
        glm::mat4 model = glm::mat4(1.0f);
        lightingShader.setMat4("model", model);

        // render the cube
        glBindVertexArray(cubeVAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);


        // also draw the lamp object
        lightingCubeShader.use();
        lightingCubeShader.setMat4("projection", projection);
        lightingCubeShader.setMat4("view", view);
        model = glm::mat4(1.0f);
        model = glm::translate(model, lightPos);
        model = glm::scale(model, glm::vec3(0.2f)); // a smaller cube
        lightingCubeShader.setMat4("model", model);

        glBindVertexArray(lightCubeVAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);


        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glDeleteVertexArrays(1, &cubeVAO);
    glDeleteVertexArrays(1, &lightCubeVAO);
    glDeleteBuffers(1, &VBO);

    glfwTerminate();
    return 0;

}
void processInput(GLFWwindow* window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);

    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
        camera.ProcessKeyboard(FORWARD, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
        camera.ProcessKeyboard(BACKWARD, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
        camera.ProcessKeyboard(LEFT, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
        camera.ProcessKeyboard(RIGHT, deltaTime);
}

void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // make sure the viewport matches the new window dimensions; note that width and 
    // height will be significantly larger than specified on retina displays.
    glViewport(0, 0, width, height);
}
// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void mouse_callback(GLFWwindow* window, double xposIn, double yposIn)
{
    float xpos = static_cast<float>(xposIn);
    float ypos = static_cast<float>(yposIn);

    if (firstMouse)
    {
        lastX = xpos;
        lastY = ypos;
        firstMouse = false;
    }

    float xoffset = xpos - lastX;
    float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top

    lastX = xpos;
    lastY = ypos;

    camera.ProcessMouseMovement(xoffset, yoffset);
}

// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
    camera.ProcessMouseScroll(static_cast<float>(yoffset));
}

2. 动态光源位置

目前,我们的光源是静止的,尝试使用sin或cos函数让光源在场景中来回移动。观察光照随时间的改变能让你更容易理解冯氏光照模型。

        //动态修改 光源位置
        lightPos.x = 1.0f + sin(glfwGetTime()) * 2.0f;
        lightPos.y = sin(glfwGetTime() / 2.0f) * 1.0f;
        lightingShader.setVec3("lightPos", lightPos);

 

 基础光照 - LearnOpenGL CN (learnopengl-cn.github.io)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/151136.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IDEA没有Add Framework Support解决办法

点击File—>Settings 点击第一个设置快捷键 点击apply和ok即可 我们要点击一下项目&#xff0c;再按快捷键ctrlk 即可

LeetCode(15)分发糖果【数组/字符串】【困难】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 135. 分发糖果 1.题目 n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 你需要按照以下要求&#xff0c;给这些孩子分发糖果&#xff1a; 每个孩子至少分配到 1 个糖果。相邻两个孩子评分更高的孩子会获…

Unity反编译:IL2CPP 打包输出的cpp文件和dll(程序集)位置、Mono打包输出的dll(程序集)位置

目录 如题&#xff1a;IL2CPP 打包输出的cpp文件和dll位置(并不会出现在APK里) 如题&#xff1a;Mono打包输出的dll位置 校验平台&#xff1a;Android 如题&#xff1a;IL2CPP 打包输出的cpp文件和dll位置(并不会出现在APK里) Unity Assets同级目录下 Temp/StagingArea/Il2…

Django视图层

视图层 django视图层&#xff1a;Django项目下的views.py文件&#xff0c;它的内部是一系列的函数或者是类,用来处理客户端的请求后处理并返回相应的数据 三板斧 HttpResponse # 返回字符串 render # 返回html页面&#xff0c;并且在返回浏览器之前还可以给html文件…

PCA降维Python demo

读这篇15年CVPR的文章&#x1f923;&#x1f923;&#x1f923;&#x1f923;&#x1f923; inproceedings{liu2015sparse,title{Sparse convolutional neural networks},author{Liu, Baoyuan and Wang, Min and Foroosh, Hassan and Tappen, Marshall and Pensky, Marianna},…

第1章 走近Java【深入理解Java虚拟机:JVM高级特性与最佳实践(第三版)】

Java技术体系所包含的内容 Java技术发展的时间线 注释

CFCA国密证书

CFCA是中国金融认证中心的缩写&#xff0c;即China Financial Certification Authority。它是一家经过中国人民银行和国家信息安全机构批准成立的国家级权威安全认证机构&#xff0c;也是国际CA浏览器联盟组织&#xff08;CA/Browser Forum&#xff09;的成员&#xff0c;遵循全…

视频剪辑全自动软件,批量剪辑去重+去水印+背景虚化+ai智能配音

软件介绍 在如今的手机时代&#xff0c;人们拍摄视频的频率越来越高&#xff0c;但大多数人往往因为缺乏专业的剪辑工具而不得不让这些珍贵的视频素材埋没在海洋中。而菜鸟视频剪辑助手的出现&#xff0c;让这些人的生活变得更为便捷。菜鸟视频剪辑助手是一款简单易用的视频剪…

ComfyUI搭建

最近心血来潮想搞下 sd 的东西, 正好赶上腾讯云有活动, 附上个活动链接,有兴趣的小伙伴可以参考下,不用谢我 高性能应用服务HAI 新品内测 一 搭建 首先先选择一个框架, 我想搭建的是 comfyui, 所以选择了Pytorch2.0.0, 里面环境都适配好了 等待个 5-8 分钟就可以了 ,因为需要加…

【微服务专题】Spring启动过程源码解析

目录 前言阅读对象阅读导航前置知识笔记正文一、SpringBoot启动过程源码解析1.1 SpringBoot启动过程源码流程图1.2 流程解析补充1.2.1 SpringApplicationRunListeners&#xff1a;SpringBoot运行过程监听器 学习总结感谢 前言 这部分只是个人的自结&#xff0c;方便后面回来看…

C++11『右值引用 ‖ 完美转发 ‖ 新增类功能 ‖ 可变参数模板』

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f383;操作环境&#xff1a; Visual Studio 2022 版本 17.6.5 文章目录 &#x1f307;前言&#x1f3d9;️正文1.右值引用1.1.什么是右值引用&#xff1f;1.2.move 转移资源1.3.左值引用 vs …

PowerPoint技巧:如何将一张图片同时加到全部幻灯片里?

想把一张图片加到PPT每一张幻灯片的同一个位置&#xff0c;如果一张一张的添加就太耗时间了&#xff0c;一起来看看如何利用母版快速设置同时添加吧。 首先&#xff0c;打开需要编辑的PPT&#xff0c;在菜单栏依次点击【视图】→【幻灯片母版】&#xff1b; 打开母版后&#x…

Redis Hotkey?3招定位+5招解决

作者总结分享 Redis Hotkey 定位和解决方法的优缺点。 作者&#xff1a;贲绍华&#xff0c;爱可生研发中心工程师&#xff0c;负责项目的需求与维护工作。其他身份&#xff1a;柯基铲屎官。 爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系…

C语言:简单的用二维数组打印杨氏三角

杨辉三角&#xff0c;又称帕斯卡三角&#xff0c;是一个数学上的规律图形。它的构造规则如下&#xff1a; 每一行的两个端点数字是1。从第三行开始&#xff0c;每个数字是它上方两个数字的和。每一行数字左右对称。 #include<stdio.h> int main() {int arr[50][50];//定…

Windows server 2012 R2系统服务器远程桌面服务激活服务器RD授权分享

Windows server 2012 R2系统服务器远程桌面服务激活服务器RD授权 二、激活服务器&#xff0c;获取许可证服务器ID和许可证密钥包ID三、激活终端服务器四、配置远程桌面会话主机授权服务器 上期我分享了Windows server 2012 R2系统服务器远程桌面服务的安装教程&#xff0c;若是…

贪吃蛇游戏和俄罗斯方块

一、创建新项目 创建一个新的项目&#xff0c;并命名。 创建一个名为images的文件夹用来存放游戏相关图片。 然后再在项目的src文件下创建一个com.xxx.view的包用来存放所有的图形界面类&#xff0c; 创建一个com.xxx.controller的包用来存放启动的入口类(控制类) package …

java初探之代理模式

代理模式 代理模式一般有三种角色&#xff1a; 没有使用代理模式的话可能就会直接去操作真实的对象 加入代理模式就是加入了 隔离 把我们的真实对象与调用者隔离了一下(代理对象) 代理对象的好处&#xff1f; 使用者(client)跟真实的对象是没有直接的交集的。不会直接操作到…

C++二分查找算法:132 模式解法二枚举2

题目及解法一&#xff1a; https://blog.csdn.net/he_zhidan/article/details/134362273 分析 第一步&#xff0c;选择各3对应的1&#xff0c;如果有多个符合对应最小的1&#xff0c;记录num[0,j)中的最小值iMin&#xff0c;如果nums[j]大于iMin&#xff0c;则m3To1 [nums[j…

开源博客项目Blog .NET Core源码学习(6:雪花算法)

Blog .NET项目中有多种数据类生成对象实例时需要唯一标识&#xff0c;一般做法要么使用GUID&#xff0c;也可以保存到数据库时使用数据库表的自增长ID&#xff0c;也可以自定义规则以确保产生不重复的唯一标识&#xff0c;而在Blog .NET项目中使用雪花算法生成唯一标识。   关…

windows安装maven,配置环境变量

官网下载&#xff1a; 其他版本找 Other Releases 配置环境变量 1、解压缩之后开始配置环境变量 2、右键此电脑&#xff0c;选中属性->高级系统设置->高级->环境变量。 3、①和②任选一个都可 ①在系统变量那边增加MAVEN_HOME&#xff0c;路径是解压缩后的文件路径。…
最新文章