OpenGL(九)——颜色

这篇具有很好参考价值的文章主要介绍了OpenGL(九)——颜色。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、前言

二、简单光源

三、光照场景

3.1 创建光源

3.2 光源顶点着色器

3.3 光源片段着色器

3.4 物体片段着色器

3.5 光源位置


一、前言

我们看到的物体颜色是通过光照在物体,然后反射到人眼成像,具体而言是物体不能吸收的颜色。如白光照射在蓝色物体上,它吸收了除了蓝光之外所有颜色,不吸收的蓝光反射到我们眼中。当物体颜色是多色光组合时(珊瑚色),该物体会反射不同强度的多个颜色,最终形成(珊瑚色)。

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

三、光照场景

3.1 创建光源

使用立方体来表示光源,创建光源的VAO;

//创建光源VAO
unsigned int lightVAO;
glGenVertexArrays(1,&lightVAO);
glBindVertexArray(lightVAO);
//绑定VBO,由于箱子的VBO数据已经包含了立方体数据,无需再次设置
glBindBuffer(GL_ARRAY_BUFFER,VBO);
//设置光源立方体顶点属性
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
glEnableVertexAttribArray(0);

3.2 光源顶点着色器

容器的顶点位置不变,仅需设置位置属性即可。

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

3.3 光源片段着色器

设置光源时要创建另一套着色器,保证其它光照着色器发生改变时不受影响。这里定义一个不变的常量白色,保证灯的颜色一直是亮的:

#version 330 core

out vec4 FragColor;

void main()
{
    FragColor = vec4(1.0);
}

3.4 物体片段着色器

这里直接定义物体颜色与光源颜色光照之后的结果即可:

#version 330 core
out vec3 FragColor;

uniform vec3 lightColor;
unifotm vec3 objectColor;

void main()
{
    FragColor = vec4(lightColor*objectColor,1.0);
}

3.5 光源位置

显示光源在3D场景中的具体位置,可以给我们直观的光源感觉,这里将光源一直设置为白色状态。

//设置灯源在世界坐标位置
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);

//把灯移动到这里,并缩小
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, lightPos);
model = glm::scale(model, glm::vec3(0.2f));

OpenGL(九)——颜色

 

#include <iostream>
#include <string>

#include "glad.h"
#include "GL/glfw3.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Shader.h"
#include "Camera.h"

//全局变量
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

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;
float deltaTime = 0.0f;
float lastFrame = 0.0f;

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

float vertices[] = {
    -0.5f, -0.5f, -0.5f,
     0.5f, -0.5f, -0.5f,
     0.5f,  0.5f, -0.5f,
     0.5f,  0.5f, -0.5f,
    -0.5f,  0.5f, -0.5f,
    -0.5f, -0.5f, -0.5f,

    -0.5f, -0.5f,  0.5f,
     0.5f, -0.5f,  0.5f,
     0.5f,  0.5f,  0.5f,
     0.5f,  0.5f,  0.5f,
    -0.5f,  0.5f,  0.5f,
    -0.5f, -0.5f,  0.5f,

    -0.5f,  0.5f,  0.5f,
    -0.5f,  0.5f, -0.5f,
    -0.5f, -0.5f, -0.5f,
    -0.5f, -0.5f, -0.5f,
    -0.5f, -0.5f,  0.5f,
    -0.5f,  0.5f,  0.5f,

     0.5f,  0.5f,  0.5f,
     0.5f,  0.5f, -0.5f,
     0.5f, -0.5f, -0.5f,
     0.5f, -0.5f, -0.5f,
     0.5f, -0.5f,  0.5f,
     0.5f,  0.5f,  0.5f,

    -0.5f, -0.5f, -0.5f,
     0.5f, -0.5f, -0.5f,
     0.5f, -0.5f,  0.5f,
     0.5f, -0.5f,  0.5f,
    -0.5f, -0.5f,  0.5f,
    -0.5f, -0.5f, -0.5f,

    -0.5f,  0.5f, -0.5f,
     0.5f,  0.5f, -0.5f,
     0.5f,  0.5f,  0.5f,
     0.5f,  0.5f,  0.5f,
    -0.5f,  0.5f,  0.5f,
    -0.5f,  0.5f, -0.5f,
};

//回调函数
void processInput(GLFWwindow* window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
    //float cameraSpeed = 0.05f; // adjust accordingly
    float cameraSpeed = 2.5f * deltaTime;
    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
        camera.ProcessKeyboard(FORWARD, deltaTime);
    //cameraPos += cameraSpeed * cameraFront;
    if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
        camera.ProcessKeyboard(BACKWARD, deltaTime);
    //cameraPos -= cameraSpeed * cameraFront;
    if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
        camera.ProcessKeyboard(LEFT, deltaTime);
    //cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
    if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
        camera.ProcessKeyboard(LEFT, RIGHT);
    //cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
}
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);
}
//3.0监听鼠标移动事件
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
    //仿止第一次进入窗口,鼠标位置较远,产生跳变
    if (firstMouse) // 这个bool变量初始时是设定为true的
    {
        lastX = xpos;
        lastY = ypos;
        firstMouse = false;
    }
    float xoffset = xpos - lastX;
    float yoffset = lastY - ypos; // 注意这里是相反的,因为y坐标是从底部往顶部依次增大的
    lastX = xpos;
    lastY = ypos;
    camera.ProcessMouseMovement(xoffset, yoffset);
}
//鼠标回调函数
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
    camera.ProcessMouseScroll(static_cast<float>(yoffset));
}

int main()
{
    //glfw 初始化
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    //创建窗体
    GLFWwindow* pWD = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Lighting", NULL, NULL);
    if (pWD == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    //注册回调
    glfwMakeContextCurrent(pWD);
    glfwSetFramebufferSizeCallback(pWD, framebuffer_size_callback);
    glfwSetCursorPosCallback(pWD, mouse_callback);
    glfwSetScrollCallback(pWD, scroll_callback);
    //glfw捕捉鼠标
    glfwSetInputMode(pWD, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
    //使用glad载入OpenGL函数地址
    int loadRet = gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
    if (!loadRet)
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
    //使能深度测试
    glEnable(GL_DEPTH_TEST);
    //着色器
    Shader lightShader("light.vs", "light.fms");
    Shader ObjShader("Obj.vs", "Obj.fms");
    //导入物体顶点数据
    unsigned int VBO, ObjVAO;
    glGenVertexArrays(1, &ObjVAO);
    glGenBuffers(1, &VBO);
    glBindVertexArray(ObjVAO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    /*index: 指定整体顶点属性索引 0 position;size:指定每个顶点属性几个构成部分;type:指定每个部分数据类型*/
    /*normalized:指定定点数据值是否需要被标准化(true (-1,1)),访问时直接转化为定点值(false)*/
    /*stride:指定数据偏移,步长;设置为0,让OpenGL去决定步长多少;*/
    /*pointer:表示位置数据在缓冲中起始位置的偏移量(Offset)*/
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    //导入光源顶点数据
    unsigned int LightVAO;
    glGenVertexArrays(1, &LightVAO);
    glBindVertexArray(LightVAO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);//前面数据已经传到内存了
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    while (!glfwWindowShouldClose(pWD))
    {
        float currentFrame = static_cast<float>(glfwGetTime());
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;
        processInput(pWD);
        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        //渲染物体
        ObjShader.use();
        ObjShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f);
        ObjShader.setVec3("objColor", 1.0f, 0.5f, 0.31f);
        //model view projection
        glm::mat4 model = glm::mat4(1.0f);
        glm::mat4 view = glm::mat4(1.0f);
        glm::mat4 projection = glm::mat4(1.0f);
        view = camera.GetViewMatrix();
        projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
        ObjShader.setMat4("model", model);
        ObjShader.setMat4("view", view);
        ObjShader.setMat4("projection", projection);
        glBindVertexArray(ObjVAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);
        //渲染 光源 (画)
        lightShader.use();
        model = glm::mat4(1.0f);
        model = glm::translate(model, lightPos);
        model = glm::scale(model, glm::vec3(0.2f));
        lightShader.setMat4("model", model);
        lightShader.setMat4("view", view);
        lightShader.setMat4("projection", projection);
        glBindVertexArray(LightVAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);
        //交换缓冲,获取事件
        glfwSwapBuffers(pWD);
        glfwPollEvents();
    }
    glDeleteVertexArrays(1, &LightVAO);
    glDeleteVertexArrays(1, &ObjVAO);
    glDeleteBuffers(1, &VBO);
    glfwTerminate();
    return 0;
}

参考:

颜色 - LearnOpenGL CN (learnopengl-cn.github.io)文章来源地址https://www.toymoban.com/news/detail-437031.html

到了这里,关于OpenGL(九)——颜色的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • unity加载场景后光照变暗

    关于unity加载场景后光照变暗的问题 最近在做场景的加载功能时,发现加载新的场景后整个场景的光照都变暗,但是如果是直接运行当前场景的话就不会,后来才发现原来是选择的光照是realtime实时光照,在一开始的场景时,它的灯光是已经渲染好了,但重新加载的时候灯光

    2024年02月15日
    浏览(53)
  • Unity Lighting -- 改善场景的反射光照效果

            先来看个案例问题,下图中,苹果的反射效果看起来是很奇怪的。          在它的表面上反射了两种不同颜色的Spot Light光源,还反射了不属于室内环境的来自天空盒的光线,这是有问题的。在解决这个问题之前,我们需要知道在Unity中反射是如何工作的。      

    2024年02月14日
    浏览(52)
  • 【图形学】30 前向渲染多光照场景代码理解

    来源:《UNITY SHADER入门精要》   我们现在要注意光源的 5 个属性: 位置、方向、颜色、强度、衰减 。   在理解代码之前,我们依然需要熟悉我们的理论,主要我们要设置两个 Pass,注意它们的不同的特性,和要做的事情。   注意,据书中所说,注意两个 Pass 中的 #

    2023年04月20日
    浏览(37)
  • OpenGL-入门-BMP像素图glReadPixels(1)实现读取屏幕中间的颜色和获取屏幕上鼠标点击位置的颜色

    glReadPixels函数用于从帧缓冲区中读取像素数据。它可以用来获取屏幕上特定位置的像素颜色值或者获取一块区域内的像素数据。下面是该函数的基本语法: x 和 y:读取区域左下角的像素坐标。 width 和 height:读取区域的宽度和高度。 format:像素数据的格式,可以是 GL_RGBA、

    2024年02月10日
    浏览(50)
  • OPenGL笔记--创建一个3D场景

    通过前面的学习,基本掌握了怎么绘制图形,使用纹理,接下来就来创建一个3D场景。 基本原理 一个复杂的场景肯定是由一些简单的图形,通过某种组合方式构建起来的,在OPenGL中也不例外;例如:在绘制立方体的时候,立方体也是由6个正方形围起来的; 基本图形 由于显卡

    2024年02月11日
    浏览(41)
  • OpenGL学习-----实用技术:场景管理与视锥体剔除

    目录 场景管理: 场景树建立: 视锥体剔除: 视锥体: 包围盒: 球: AABB: 判断是否在视锥体内: 包围盒为球体: 包围盒为AABB: 空间加速: 场景树的建立,这里讲一下建树,树里面保存根据自己的model矩阵,这个矩阵需要根据父物体的model矩阵做出相对变化。出于学习目

    2023年04月23日
    浏览(32)
  • UE5 Lumen实时全局光照系统简单分析

      做这个调研分析的时间应该在去年(2022)十二月初的几天时间,主要是通过UE官方的直播讲解和在SIGGRAPH 2021(Radiance Caching for Real-Time Global Illumination)及2022(Lumen: Real-time Global Illumination in Unreal Engine 5)的两次分享进行学习了解。没有看具体源码,所以文章内容全部为个

    2024年02月04日
    浏览(42)
  • 实验二:OpenGL的简单动画

    一、实验目的 1.掌握OpenGL的闲置函数。 2.掌握OpenGL的时间函数。 3.掌握OpenGL的简单动画功能。 4.了解OpengGL裁剪窗口、视区、显示窗 口的概念和它们之间的关系。 5.进一步掌握OpenGL基本图元的绘制。 二、实验内容 1.闲置函数的使用与简单动画。 1)旋转的六边形如实验图2-1所

    2024年02月05日
    浏览(37)
  • OpenGL太阳系行星系统简单实现

    使用OpenGL(glfw, glad)模拟太阳系(地球、月球、太阳)系统,涉及三维图形变换、坐标系统,光照模型(待添加)、键盘鼠标事件处理等内容,在main函数中封装了绝大部分的OpenGL接口,极大的减少了代码量,操作简便。 Shader.h Camera.h与Texture.h封装着色器、摄像机与纹理类,其

    2024年02月04日
    浏览(44)
  • vtk三维场景基本要素 灯光、相机、颜色、纹理映射 简介

    整理一下VTK  三维场景基本要素,后面会一一进行整理; 1. 灯光 vtkLight 剧场里有各式各样的灯光,三维渲染场景中也一样,可以有多个灯光存在。灯光和相机 是三维渲染场景必备的要素,vtkRenderer会自动创建默认的灯光和相机;   vtkLight可以分为位置灯光(Positional Light,也叫聚

    2024年02月20日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包