OpenGL — GLFW — 颜色
OpenGL — GLFW — 颜色
参考教程:https://learnopengl-cn.readthedocs.io/zh/latest/02%20Lighting/01%20Colors/
既然,网络上已经有现成的教程了,我为什么还有在写一遍教程呢?
这个教程不是给大家写的,而是给我自己写的,算是我的学习笔记吧。我将编程序的重点提起出来,并将我的经验和遇到的问题记下来,为日后的我做参考用的。知识会随着时间的流过,而慢慢的被遗忘,当日后有一个项目要用到OpenGL的知识时,那个时候的我可能已经将当初学到的OpenGL忘记的擦不多了,这个时候,我就需要过去的我来帮助我,可以这样理解,跨越时空的两个我在完成一个项目!不错,这就是记笔记的作用。
给模型上颜色,两个步骤:
- 编写片段着色器
- 在主程序中给片段着色器赋值
- 在主主函数中,使用片段着色器
你可能会问,颜色有什么好讲的?我想说:你问对了,真的没有什么好讲的。就是定义一个变量:
glm::vec3 color(1.0f, 0.5f, 0.31f); // 珊瑚红(Coral)
编写程序步骤
第1步:
程序
先顶点着色器程序,就用个精简版的程序:(顶点着色器(Vertex Shader)文件名为:color.vs)
#version 330 core
layout (location = 0) in vec3 position;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
}
解释
layout (location = 0) in vec3 position;
得到CPP程序中是ID是0的数据,将ID为0的数据的物理意义定义为顶点位置
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
这些变量是需要在CPP程序中等待赋值的。
归根结底,这三个变量都是4*4的矩阵,都是作用于模型的每一个顶点的。
但是他们代表着不同的物理意义:
model | 模型自身的姿态矩阵。姿态:旋转和平移组成。 |
---|---|
view | 摄像机姿态矩阵。 |
projection | 透视矩阵。 |
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
}
gl_Position是GLSL(OpenGL Shading Language)着色语言中的一个内置变量,即输出的顶点位置。
总结:这个顶点着色器的作用就是:更新顶点的位置。
第2步:
程序
编写片段着色器:(片段着色器(Fragment shader)文件命名为:color.frag)
#version 330 core
out vec4 color;
uniform vec3 objectColor;
uniform vec3 lightColor;
void main()
{
color = vec4(lightColor * objectColor, 1.0f);
}
讲解
out vec4 color;
输出的color变量。
uniform vec3 objectColor;
uniform vec3 lightColor;
这两个值在CPP程序中被赋值,分别表示物体色 和 光源颜色。
void main()
{
color = vec4(lightColor * objectColor, 1.0f);
}
将光源颜色与物体颜色相乘,即两个向量相乘,得到最终的颜色。因为定义的color是4维向量,objectColor和lightColor是3维向量。所以这里给color赋值的时候要这样做color = vec4(vec3, 1.0f);
总结: 这个片段着色器做的事情:更新物体颜色。
第3步
编写CPP程序模板
#include <iostream>
#include <cmath>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// Other Libs
#include <SOIL.h>
// GLM Mathematics
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
// Other includes
#include <learnopengl\shader.h>
#include <learnopengl\camera.h>
#include <learnopengl\model.h>
// Function prototypes
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);
void do_movement();
// Window dimensions
const GLuint WIDTH = 800, HEIGHT = 800;
// Camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
GLfloat lastX = WIDTH / 2.0;
GLfloat lastY = HEIGHT / 2.0;
bool keys[1024];
// Deltatime
GLfloat deltaTime = 0.0f; // Time between current frame and last frame
GLfloat lastFrame = 0.0f; // Time of last frame
// The MAIN function, from here we start the application and run the game loop
int main()
{
// Init GLFW
glfwInit();
// Set all the required options for GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
// Create a GLFWwindow object that we can use for GLFW's functions
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "AoboSir OpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
// Set the required callback functions
glfwSetKeyCallback(window, key_callback);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
// GLFW Options
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
glewExperimental = GL_TRUE;
// Initialize GLEW to setup the OpenGL Function pointers
glewInit();
// Define the viewport dimensions
glViewport(0, 0, WIDTH, HEIGHT);
// OpenGL options
glEnable(GL_DEPTH_TEST);
//定义着色器类对象
//定义模型类对象
// Game loop
while (!glfwWindowShouldClose(window))
{
// Calculate deltatime of current frame
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
glfwPollEvents();
do_movement();
// Clear the colorbuffer
//glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClearColor(0.41f, 0.41f, 0.41f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//给着色器进行赋值
//让模型使用这个着色器对象,显示模型
// Swap the screen buffers
glfwSwapBuffers(window);
}
// Terminate GLFW, clearing any resources allocated by GLFW.
glfwTerminate();
return 0;
}
// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
if (key >= 0 && key < 1024)
{
if (action == GLFW_PRESS)
keys[key] = true;
else if (action == GLFW_RELEASE)
keys[key] = false;
}
}
void do_movement()
{
// Camera controls
if (keys[GLFW_KEY_W])
camera.ProcessKeyboard(FORWARD, deltaTime);
if (keys[GLFW_KEY_S])
camera.ProcessKeyboard(BACKWARD, deltaTime);
if (keys[GLFW_KEY_A])
camera.ProcessKeyboard(LEFT, deltaTime);
if (keys[GLFW_KEY_D])
camera.ProcessKeyboard(RIGHT, deltaTime);
}
bool firstMouse = true;
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
if(glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_LEFT )){
if (firstMouse)
{
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
GLfloat xoffset = xpos - lastX;
GLfloat yoffset = ypos - lastY; // Reversed since y-coordinates go from bottom to left
lastX = xpos;
lastY = ypos;
camera.ProcessMouseMovement(glm::radians(xoffset), glm::radians(yoffset));
} else {
firstMouse = true;
}
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
camera.ProcessMouseScroll(glm::radians(yoffset) );
}
注意:
1.glm::radians(angle)
这个函数是将输入的角度转换为弧度。
2.glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_LEFT )
函数,如果鼠标左键按下,函数会返回非零数据;如果鼠标左键没有被按下,函数会返回0.
第4步
定义着色器对象和模型对象,给着色器对象赋值,并让模型对象使用着色器对象,显示模型。
定义着色器对象和模型对象
//定义着色器类对象
// Build and compile our shader program
Shader lightingShader("shader/color.vs", "shader/color.frag");
Shader lampShader("shader/lamp.vs", "shader/lamp.frag");
//定义模型类对象
Model ourModel("meshes/TexMesh.obj");
Model lampModel("meshes/Light_Bulb.obj");
给着色器进行赋值
//给着色器进行赋值
// Use cooresponding shader when setting uniforms/drawing objects
lightingShader.Use();
GLint objectColorLoc = glGetUniformLocation(lightingShader.Program, "objectColor");
GLint lightColorLoc = glGetUniformLocation(lightingShader.Program, "lightColor");
glUniform3f(objectColorLoc, 1.0f, 0.5f, 0.31f);
glUniform3f(lightColorLoc, 1.0f, 1.0f, 1.0f);
// Create camera transformations
glm::mat4 view;
view = camera.GetViewMatrix();
glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
// Get the uniform locations
GLint modelLoc = glGetUniformLocation(lightingShader.Program, "model");
GLint viewLoc = glGetUniformLocation(lightingShader.Program, "view");
GLint projLoc = glGetUniformLocation(lightingShader.Program, "projection");
// Pass the matrices to the shader
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
// Draw the loaded model
glm::mat4 model;
model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f)); // It's a bit too big for our scene, so scale it down
glUniformMatrix4fv(glGetUniformLocation(lightingShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
让模型使用这个着色器对象,显示模型
//让模型使用这个着色器对象,显示模型
ourModel.Draw(lightingShader);
大功告成,第6步,运行程序
(这其实是以一张倒人脸的背面,你现在看到的是一片珊瑚红色,是因为在我们的这个着色器是最简单的着色器,并且我们没有使用模型的点的法线向量,所以没有阴影的效果。)
我们继续学习下一课。
参考网站:
http://www.cnblogs.com/zhanglitong/p/3209282.html
http://www.glfw.org/docs/latest/group__input.html#gac1473feacb5996c01a7a5a33b5066704
http://learnopengl.com/code_viewer.php?code=model_loading/model_diffuse
下载一个灯泡模型:http://tf3dm.com/3d-model/light-bulb-simple-studio-9032.html
OpenGL — GLFW — 颜色的更多相关文章
- OpenGL学习--------颜色的选择
OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式.无论哪种颜色模式,计算机都必须为每一个像素保存一些数据.不同的是,RGBA模式中,数据直接就代表了颜色:而颜色索引模式中,数据代表的是 ...
- 第03课 OpenGL 添加颜色
添加颜色: 作为第二课的扩展,我将叫你如何使用颜色.你将理解两种着色模式,在下图中,三角形用的是光滑着色,四边形用的是平面着色 上一课中我教给您三角形和四边形的绘制方法.这一课我将教您给三角形和四边形 ...
- OpenGL glfw
{ https://github.com/glfw/glfw }
- OpenGL学习进程(11)第八课:颜色绘制的详解
本节是OpenGL学习的第八个课时,下面将详细介绍OpenGL的颜色模式,颜色混合以及抗锯齿. (1)颜色模式: OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式. R ...
- opengl& 颜色
颜色 简介 颜色的显示模式分为两种: RGBA显示模式 颜色索引显示模式(使用颜色映射表,映射表提供了索引,可以混合基本的红,绿,蓝色值). RGBA模式可以选择的颜色数量多于颜色索引模式.一般而言, ...
- opengl库区分:glut、freeglut、glfw、glew、gl3w、glad
//oepngl库 opengl原生库 gl* 随opengl一起发布 opengl实用库 glu* 随opengl一起发布 opengl实用工具库glut glut* 需要下载配置安装(太老了!) ...
- OpenGL 使用GLFW创建全屏窗口
OpenGL 使用GLFW创建全屏窗口 GLFW库里面的glfwCreateWindow()函数是用来创建窗口的函数. 这样函数的原型是: GLFWwindow* glfwCreateWindow(i ...
- OpenGL(三) RGBA颜色设置
OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式. 像素点附加颜色信息之后,就必须为每一个像素点额外分配一个内存空间保存该点的颜色信息,对于RGBA颜色模式,保存的数据直接代表了颜色, ...
- OpenGL学习——搭建OpenGL运行环境——生成一个空白视口——基于GLFW&GLEW
最近学习OpenGL,读OpenGL宝典一头蒙,各种gl函数不知所云.逐决定先搭OpenGL运行环境,详细如下. 1.首先OpenGL是什么?是一个标准规范,是一个巨大的状态机,并无具体实现,大多数实 ...
随机推荐
- c的详细学习(2)数据类型,运算符与表达式
本节用来介绍c语言中的数据类型和运算符. (1)c语言的基本符号: 任何一种基本语言都有自己的基本词汇表.c语言的基本词汇表有一下几部分: *数字10个: *英文字母:大小 ...
- Python 3 接口与归一化设计
一.接口与归一化设计: 1.归一化让使用者无需关心对象的类是什么,只需要知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度. 2.归一化使得高层的外部使用者可以不加区分的处理所有接口兼 ...
- 一个例子看懂所有nodejs的官方网络demo
今天看群里有人用AI技术写了个五子棋,正好用的socket.io,本身我自己很久没看nodejs了,再加上Tcp/IP的知识一直很弱,我就去官网看了下net.socket 发现之前以为懂的一个官方例子 ...
- 对unidbgrid的单元格操作
一.使某行某列单元格disabled: 1. UniStringGrid -> Options -> goEditing = true 2. UniStringGrid -> Ext ...
- python-socket2
UDP,服务端 #! /usr/bin/env python #coding=utf-8 import socket #创建socket,指定ipv4,udp类型 s = socket.socket( ...
- Oracle忘记用户名密码
一.oracle 11g登录服务开启 成功安装Oracle 11g后,共有7个服务,这七个服务的含义分别为:1. Oracle ORCL VSS Writer Service:Oracle卷映射拷贝写 ...
- Linux CentOS 6.5 64位 静默安装Oracle11g 云主机
本例: 通过SSH远程连接云主机,上传oracle11g安装包,在centos6.5上无图形化界面静默安装oracle11g. 涉及工具及环境: 1.本地环境windows7+ssh远程连接工具xSh ...
- bzoj 4540: [Hnoi2016]序列 莫队
题目: 给定长度为n的序列:a1,a2,-,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,-,ar- 1,ar.若1≤l≤s≤t≤r≤n,则称a[s:t]是a ...
- nvidia-docker 安装
1.安装docker 官方网址安装说明 https://docs.docker.com/install/linux/docker-ce/ubuntu/ 2.ubuntu 14.04/16.04/18. ...
- spark减少提交jar包处理
spark一个应用,算上依赖一百多兆.每一次都如此,坑. 首先是<packing>jar</packing>这只为打包为jar,在plugin中增加一个assembly插件,这 ...