LearnOpenGL-光照-1.颜色

news2024/10/1 19:21:52

本人刚学OpenGL不久且自学,文中定有代码、术语等错误,欢迎指正

我写的项目地址:https://github.com/liujianjie/LearnOpenGLProject

文章目录

  • 颜色
  • OpenGL代码例子

颜色

  • 物体颜色简介

    我们在现实生活中看到某一物体的颜色并不是这个物体真正拥有的颜色,而是它所反射的(Reflected)颜色

    那些不能被物体所吸收(Absorb)的颜色(被拒绝的颜色)就是我们能够感知到的物体的颜色

  • 举个栗子

    (太阳光能被看见的白光其实是由许多不同的颜色组合而成的(如下图所示))

    如果我们将白光照在一个蓝色的玩具上,这个蓝色的玩具会吸收白光中除了蓝色以外的所有子颜色,不被吸收的蓝色光被反射到我们的眼中,让这个玩具看起来是蓝色的

  • 图示

  • 在opengl中

    在图中我们有一个白色的太阳,所以我们也将光源设置为白色

    当我们把光源的颜色与物体的颜色值相乘,所得到的就是这个物体所反射的颜色(也就是我们所感知到的颜色)

  • opengl例子

    glm::vec3 lightColor(1.0f, 1.0f, 1.0f);
    glm::vec3 toyColor(1.0f, 0.5f, 0.31f);
    glm::vec3 result = lightColor * toyColor; // = (1.0f, 0.5f, 0.31f);
    

    我们可以看到玩具的颜色吸收了白色光源中很大一部分的颜色,但它根据自身的颜色值对红、绿、蓝三个分量都做出了一定的反射。这也表现了现实中颜色的工作原理。

    由此,我们可以定义物体的颜色为物体从一个光源反射各个颜色分量的大小

    glm::vec3 lightColor(0.0f, 1.0f, 0.0f);
    glm::vec3 toyColor(1.0f, 0.5f, 0.31f);
    glm::vec3 result = lightColor * toyColor; // = (0.0f, 0.5f, 0.0f);
    

    可以看到,并没有红色和蓝色的光让我们的玩具来吸收或反射。这个玩具吸收了光线中一半的绿色值,但仍然也反射了一半的绿色值。玩具现在看上去是深绿色(Dark-greenish)的。我们可以看到,如果我们用绿色光源来照射玩具,那么只有绿色分量能被反射和感知到,红色和蓝色都不能被我们所感知到。这样做的结果是,一个珊瑚红的玩具突然变成了深绿色物体。

OpenGL代码例子

  • 代码

    glsl

    #version 330 core
    layout (location = 0) in vec3 aPos;
    
    uniform mat4 view;
    uniform mat4 projection;
    uniform mat4 model;
    void main()
    {
        gl_Position = projection * view * model * vec4(aPos, 1.0);
    }
    
    #version 330 core
    out vec4 FragColor;
    
    uniform vec3 objectColor;
    uniform vec3 lightColor;
    
    void main()
    {
    	FragColor = vec4(lightColor * objectColor, 1.0f);
    }
    

    cpp

    // 物体的光照shader
    Shader lightingShader("assest/shader/2光照/2.1.1.color.vs", "assest/shader/2光照/2.1.1.color.fs");
    // 光源shader
    Shader lightCubeShader("assest/shader/2光照/2.1.2.light_cube.vs", "assest/shader/2光照/2.1.2.light_cube.fs");
    
    // 0.1顶点数据
    float vertices[] = {
        -0.5f, -0.5f, -0.5f,
        ..........
    };
    unsigned int VBO, cubeVAO;
    glGenVertexArrays(1, &cubeVAO);
    glGenBuffers(1, &VBO);
    // 1. 绑定顶点数组对象
    glBindVertexArray(cubeVAO);
    // 2. 把我们的CPU的顶点数据复制到GPU顶点缓冲中,供OpenGL使用
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    // 3. 设定顶点属性指针,来解释顶点缓冲中的顶点属性布局
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    
    // 重新创建一个顶点数组,同样指向这个顶点缓冲对象VBO
    unsigned int lightCubeVAO;
    glGenVertexArrays(1, &lightCubeVAO);
    glBindVertexArray(lightCubeVAO);
    // 重复利用顶点缓冲对象
    glBindBuffer(GL_ARRAY_BUFFER, VBO);// 绑定的是vbo
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    
    // render loop
    // -----------
    while (!glfwWindowShouldClose(window))
    {
        ......
        // render
        // ------
        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        // 绑定着色器
        lightingShader.use();
        lightingShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f);
        lightingShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f);
    
        // 观察/投影变换
        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);
    
        // 世界变换
        glm::mat4 model = glm::mat4(1.0f);
        lightingShader.setMat4("model", model);
    
        // 渲染这个cube
        glBindVertexArray(cubeVAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);
    
        // 同样渲染白色的cube当做太阳
        lightCubeShader.use();
        lightCubeShader.setMat4("projection", projection);
        lightCubeShader.setMat4("view", view);
        model = glm::mat4(1.0f);
        model = glm::translate(model, lightPos);
        model = glm::scale(model, glm::vec3(0.2f)); // a smaller cube
        lightCubeShader.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();
    }
    
  • 效果

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++ Primer Plus 第6版 读书笔记(5)第5章 循环和关系表达式

第5章 循环和关系表达式 本章内容包括&#xff1a;for 循环。表达式和语句。递增运算符和递减运算符&#xff1a;和−−。组合赋值运算符。复合语句&#xff08;语句块&#xff09;。逗号运算符。关系运算符&#xff1a;>、>、 、<、<和!。while 循环。typedef 工…

java怎么写接口,java开发api接口教程

在大家的工作中&#xff0c;经常写界面。 而且&#xff0c;最常用的是http接口。 但是&#xff0c;对于初学者Java工作人员来说&#xff0c;写http界面还很难。 那么&#xff0c;用实例来说明吧。 一、建设项目 首先&#xff0c;生成SpringBoot项目。 省略如何构建此处&#x…

proteus中仿真arduino驱动模拟器件(蜂鸣器继电器电机)

模拟器件如蜂鸣器、继电器、直流电机等在arduino电路中&#xff0c;如果我们接在数字管脚上来驱动往往可能因为驱动电流不够而达不到预期效果&#xff0c;或者没有动作或者没有动静。这篇博文我们专门来讨论一下如何驱动他们。 文章目录一、典型电路1、蜂蜜器(1)蜂鸣器的种类:(…

tun驱动之write

tun的write执行类型下面的代码 int fd open("/dev/net/tun", O_RDWR) write(fd, buf, len); 首先要明确一点&#xff0c;向tun驱动写的数据&#xff0c;最后会进入网络协议栈&#xff0c;相当于外部的数据通过网卡进入网络协议栈。所以写入tun驱动的数据&#xff0…

LSTM网络:一种强大的时序数据建模工具

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️&#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

32位Ubuntu系统安装visual studio code

Step.01 下载vscode安装包 vscode自1.36版本后停止支持32位linux系统&#xff0c;所以要使用<1.36版本。1.33版本下载地址&#xff1a; Visual Studio Code March 2019See what is new in the Visual Studio Code March 2019 Release (1.33)https://code.visualstudio.com…

nvm的使用

nvm工具 nvm是什么nvm下载与安装nvm的基本使用 1、nvm介绍 1.1、基于node的开发 在介绍nvm之前&#xff0c;先介绍下前端开发中关于node的使用。目前前端不管是基于vue或者react框架的开发&#xff0c;都是基于node环境下&#xff0c;进行包的管理与开发的。而不同项目组&a…

work-notes(23):结合typora、git、gitee实现云存储笔记完成的操作过程

时间&#xff1a;2023-03-07 文章目录摘要一、下载 typora二、安装 Git三、创建连接远程仓库四、使用 Git 上传到远程仓库五、到gitee上查看总结摘要 由于很想找一个好用&#xff0c;又有云存储的笔记软件。之前用过 有道笔记&#xff08;还行&#xff0c;量大了难找&#xff…

「MySQL进阶」为什么MySQL用B+树做索引而不用二叉查找树、平衡二叉树、B树

「MySQL进阶」为什么MySQL用B树做索引而不用二叉查找树、平衡二叉树、B树 文章目录「MySQL进阶」为什么MySQL用B树做索引而不用二叉查找树、平衡二叉树、B树一、概述二、二叉查找树三、平衡二叉树四、B树五、B树六、聚集索引和非聚集索引七、利用聚集索引和非聚集索引查找数据利…

剑指 Offer 67 把字符串转换成整数

摘要 面试题67. 把字符串转换成整数 一、字符串解析 根据题意&#xff0c;有以下四种字符需要考虑&#xff1a; 首部空格&#xff1a; 删除之即可&#xff1b;符号位&#xff1a;三种情况&#xff0c;即 , − , 无符号"&#xff1b;新建一个变量保存符号位&#xff0…

螯合剂p-SCN-Bn-TCMC,282097-63-6,双功能配体化合物应用于光学成像应用

p-SCN-Bn-TCMC 反应特点&#xff1a;p-SCN-Bn-TCMC属于双功能配体是螯合剂&#xff0c;也具有共价连接到生物靶向载体&#xff08;如抗体、肽和蛋白质&#xff09;的反应位点。应用于核医学、MRI和光学成像应用。西安凯新生物科技有限公司供应的杂环化合物及其衍生物可制作为具…

消息队列理解

为什么使用消息队列 使⽤消息队列主要是为了&#xff1a; 减少响应所需时间和削峰。降低系统耦合性&#xff08;解耦/提升系统可扩展性&#xff09;。 当我们不使⽤消息队列的时候&#xff0c;所有的⽤户的请求会直接落到服务器&#xff0c;然后通过数据库或者 缓存响应。假…

GPU是什么

近期ChatGPT十分火爆&#xff0c;随之而来的是M国开始禁售高端GPU显卡。M国想通过禁售GPU显卡的方式阻挡中国在AI领域的发展。 GPU是什么&#xff1f;GPU&#xff08;英语&#xff1a;Graphics Processing Unit&#xff0c;缩写&#xff1a;GPU&#xff09;是显卡的“大脑”&am…

给比特币“雕花” 增值还是累赘?

比特币网络也能发NFT了&#xff0c;大玩家快速入场。3月6日&#xff0c;Yuga Labs开启了TwelveFold拍卖会&#xff0c;该项目是Yuga Labs在比特币区块链网络上发行的首个NFT合集&#xff0c;内含300个艺术品。 在没有智能合约的比特币网络造NFT&#xff0c;没那么友好。但Web3…

Jmeter+Ant+Jenkins自动化搭建之报告优化

平台简介一个完整的接口自动化测试平台需要支持接口的自动执行&#xff0c;自动生成测试报告&#xff0c;以及持续集成。Jmeter支持接口的测试&#xff0c;Ant支持自动构建&#xff0c;而Jenkins支持持续集成&#xff0c;所以三者组合在一起可以构成一个功能完善的接口自动化测…

概率论与数理统计相关知识

本博客为《概率论与数理统计&#xff0d;&#xff0d;茆诗松&#xff08;第二版&#xff09;》阅读笔记&#xff0c;目的是查漏补缺前置知识数学符号连乘符号&#xff1a;&#xff1b;总和符号&#xff1a;&#xff1b;“任意”符号&#xff1a;∀&#xff1b;“存在”符号&…

IDEA项目中配置Maven镜像源(下载源)

目录前言一、IDEA中Maven的位置二、修改Maven的配置文件2.1 配置文件2.2 修改镜像源三、在IDEA中使配置文件生效四、配置文件和本地仓库迁移前言 在使用IDEA搭建项目的过程中&#xff0c;我们发现框架的jar包下载非常缓慢&#xff0c;这是因为国内访问Maven仓库速度较低&#…

构建GRE隧道打通不同云商的云主机内网

文章目录1. 环境介绍2 GRE隧道搭建2.1 华为云 GRE 隧道安装2.2 阿里云 GRE 隧道安装3. 设置安全组4. 验证GRE隧道4.1 在华为云上 ping 阿里云云主机内网IP4.2 在阿里云上 ping 华为云云主机内网IP5. 总结1. 环境介绍 华为云上有三台云主机&#xff0c;内网 CIDR 是 192.168.0.0…

TensoRT8.4_cuda11.6 sampleOnnxMNIST运行生成

1、版本信息 win10电脑环境&#xff1a; TensorRT:8.4.1.5CUDA: 11.6VS: 2019 环境安装成功后&#xff0c;使用sampleOnnxMNIST测试 2、VS2019环境配置 用vs打开sampleOnnxMNIST项目&#xff0c;位置在 D:\TensorRT-8.4.1.5\samples\sampleOnnxMNIST &#xff08;1&#xf…

创建SpringBoot工程详细步骤

new新建一个项目选择Spring Initializr, 然后配置一下地址, 可以如下图使用阿里云的,(因为国外的Spring官网可能不稳定) 下面这三个地址(选一个)能用的用上就行 https://start.spring.io(默认) https://start.springboot.io https://start.aliyun.com 然后 然后点击Finish…