文章目录

  • 一、颜色
  • 二、光照基础
    • 2.1环境光照
    • 2.2漫反射光照
    • 2.3镜面光照

如何才能更为真实的表现出生活中的环境呢?其实现实生活它已经给了我们答案,就是光照。了解光与颜色构造之间的关系,我们才能更好的创造出更为真实的场景颜色。

一、颜色

其实只要有一些基础的物理知识,我们就可以了解到物体在我们人眼中的颜色是光接触物体之后,物体反射到我们眼中的颜色。理解了这一点下面就比较容易用代码实现了,如下所示:

Camera.h

#ifndef CAMERA_H
#define CAMERA_H#include <glad/glad.h>
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"#include <vector>//定义相机移动的选项
enum Camera_Movement {FORWARD,BACKWARD,LEFT,RIGHT
};//默认的相机参数
const float YAW = -90.0f;
const float PITCH = 0.0f;
const float SPEED = 2.5f;
const float SENSITIVITY = 0.1f;
const float ZOOM = 45.0f;//相机类
class Camera
{public:// camera Attributesglm::vec3 Position;glm::vec3 Front;glm::vec3 Up;glm::vec3 Right;glm::vec3 WorldUp;// euler Anglesfloat Yaw;float Pitch;// camera optionsfloat MovementSpeed;float MouseSensitivity;float Zoom;// constructor with vectorsCamera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM){Position = position;WorldUp = up;Yaw = yaw;Pitch = pitch;updateCameraVectors();}// constructor with scalar valuesCamera(float posX, float posY, float posZ, float upX, float upY, float upZ, float yaw, float pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM){Position = glm::vec3(posX, posY, posZ);WorldUp = glm::vec3(upX, upY, upZ);Yaw = yaw;Pitch = pitch;updateCameraVectors();}// returns the view matrix calculated using Euler Angles and the LookAt Matrixglm::mat4 GetViewMatrix(){return glm::lookAt(Position, Position + Front, Up);}// processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems)void ProcessKeyboard(Camera_Movement direction, float deltaTime){float velocity = MovementSpeed * deltaTime;if (direction == FORWARD)Position += Front * velocity;if (direction == BACKWARD)Position -= Front * velocity;if (direction == LEFT)Position -= Right * velocity;if (direction == RIGHT)Position += Right * velocity;}// processes input received from a mouse input system. Expects the offset value in both the x and y direction.void ProcessMouseMovement(float xoffset, float yoffset, GLboolean constrainPitch = true){xoffset *= MouseSensitivity;yoffset *= MouseSensitivity;Yaw += xoffset;Pitch += yoffset;// make sure that when pitch is out of bounds, screen doesn't get flippedif (constrainPitch){if (Pitch > 89.0f)Pitch = 89.0f;if (Pitch < -89.0f)Pitch = -89.0f;}// update Front, Right and Up Vectors using the updated Euler anglesupdateCameraVectors();}// processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axisvoid ProcessMouseScroll(float yoffset){Zoom -= (float)yoffset;if (Zoom < 1.0f)Zoom = 1.0f;if (Zoom > 45.0f)Zoom = 45.0f;}private:// calculates the front vector from the Camera's (updated) Euler Anglesvoid updateCameraVectors(){// calculate the new Front vectorglm::vec3 front;front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));front.y = sin(glm::radians(Pitch));front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));Front = glm::normalize(front);//重新计算相机的右向量与上向量Right = glm::normalize(glm::cross(Front, WorldUp));  // normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.Up = glm::normalize(glm::cross(Right, Front));}
};
#endif

而关于Shader着色器类已经在前面的文章提过,所以在这里就直接进入正题。

shader_light_cube.vs

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

shader_light_cube.fs

#version 330 core
out vec4 FragColor;void main()
{FragColor = vec4(1.0); //设置为白色
}

shader_color_cube.vs

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

shader_color_cube.fs

#version 330 core
out vec4 FragColor;uniform vec3 objectColor;
uniform vec3 lightColor;void main()
{FragColor = vec4(lightColor * objectColor, 1.0);      //利用反射的原理来计算出物体的颜色
}

Practice.h

#pragma once#include<glad\glad.h>
#include<GLFW\glfw3.h>#include"shader.h"
#include"Camera.h"
#include<iostream>namespace Light {const unsigned int SCR_WIDTH = 800;const unsigned int SCR_HEIGHT = 600;Camera camera(glm::vec3(0.0f, 0.0f, 5.0f));float lastX = SCR_WIDTH / 2.0f;float lastY = SCR_HEIGHT / 2.0f;bool firstMouse = true;// timingfloat deltaTime = 0.0f;float lastFrame = 0.0f;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){glViewport(0, 0, width, height);        //重新设置视口大小}//鼠标事件void mouse_callback(GLFWwindow* window, double xpos, double ypos){if (firstMouse){lastX = xpos;lastY = ypos;firstMouse = false;}float xoffset = xpos - lastX;float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to toplastX = xpos;lastY = ypos;camera.ProcessMouseMovement(xoffset, yoffset);}//滚轮事件void scroll_callback(GLFWwindow* window, double xoffset, double yoffset){camera.ProcessMouseScroll(yoffset);}void lightv1() {glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);GLFWwindow *window = glfwCreateWindow(800, 600, "Light", 0, 0);if (window==NULL) {std::cout << "Creating window is failed" << std::endl;glfwTerminate();return;}glfwMakeContextCurrent(window);glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);glfwSetCursorPosCallback(window, mouse_callback);glfwSetScrollCallback(window, scroll_callback);glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "Failed to initialize GLAD" << std::endl;return;}int viewWidth, viewHeight;glfwGetFramebufferSize(window, &viewWidth, &viewHeight);glViewport(0, 0, viewWidth, viewHeight);Shader colorShader("../Shader/shader_color.vs", "../Shader/shader_color.fs");Shader cubeShader("../Shader/shader_light_cube.vs", "../Shader/shader_light_cube.fs");//顶点数据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,};//为数据分配缓冲区unsigned int colorVAO, VBO;glGenVertexArrays(1, &colorVAO);glBindVertexArray(colorVAO);glGenBuffers(1, &VBO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);unsigned int cubeVAO;glGenVertexArrays(1,&cubeVAO);glBindVertexArray(cubeVAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);glEnable(GL_DEPTH_TEST);//光源的位置glm::vec3 lightPos(1.2f, 1.0f, 2.0f);while (!glfwWindowShouldClose(window)) {float currentFrame = glfwGetTime();deltaTime = currentFrame - lastFrame;lastFrame = currentFrame;processInput(window);glClearColor(0.1f, 0.1f, 0.1f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glm::mat4 model = glm::mat4(1.0f);glm::mat4 view = glm::mat4(1.0f);glm::mat4 projection = glm::mat4(1.0f);//绘制有颜色的立方体colorShader.use();colorShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f);colorShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f);projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);view = camera.GetViewMatrix();colorShader.setMat4("projection", projection);colorShader.setMat4("view", view);colorShader.setMat4("model", model);glBindVertexArray(colorVAO);glDrawArrays(GL_TRIANGLES, 0, 36);//绘制光源立方体cubeShader.use();//view = glm::translate(view, glm::vec3(0.0f, 0.0f, -10.0f));//view = glm::lookAt(glm::vec3(0.0f, 0.0f, 10.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));cubeShader.setMat4("projection", projection);cubeShader.setMat4("view", view);model = glm::mat4(1.0f);model = glm::translate(model, lightPos);       //将灯平移到lightPos位置model = glm::scale(model, glm::vec3(0.3f));       //并对其进行一定程度的缩放cubeShader.setMat4("model", model);glBindVertexArray(cubeVAO);glDrawArrays(GL_TRIANGLES, 0, 36);glfwSwapBuffers(window);glfwPollEvents();}glDeleteVertexArrays(1, &colorVAO);glDeleteVertexArrays(1, &cubeVAO);glDeleteBuffers(1, &VBO);glfwTerminate();}
}

main.cpp

#include"Practice.h"int main() {Light::lightv1();return 0;
}

运行效果:

二、光照基础

这部分主要是学习怎么使用冯氏光照模型:环境(Ambient)、漫反射(Diffuse)和镜面(Specular)光照。

2.1环境光照

其实就是添加了一个环境因子来控制光的强度,以此来影响物体反射的颜色。

shader_ambient.fs

#version 330 core
out vec4 FragColor;uniform vec3 lightColor;
uniform vec3 objectColor;void main()
{//环境因子float ambientStrength = 0.3;vec3 ambient = ambientStrength * lightColor;   //利用环境因子来控制光强vec3 result = ambient * objectColor;FragColor = vec4(result, 1.0);
}

运行效果:

2.2漫反射光照

漫反射,是投射在粗糙表面上的光向各个方向反射的现象。但说到底这仍然是一种反射现象,那么其就与物体表面的法向量有着很大的关系,物体表面各点的法向量不一致,才造成了反射光线“漫射”现象,因此冯氏光照模型引入了散射因子这一概念来更好的模拟光照。不过因为本次的对象是一个较为理想的立方体,所以其每个面的法向量默认是一致的,实现过程如下所示。

shader_basic_lighting.vs

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) 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 = aNormal;  gl_Position = projection * view * vec4(FragPos, 1.0);
}

shader_basic_lighting.fs

#version 330 core
out vec4 FragColor;in vec3 Normal;
in vec3 FragPos;  uniform vec3 lightPos;
uniform vec3 lightColor;
uniform vec3 objectColor;void main()
{//环境因子float ambientStrength = 0.1;vec3 ambient = ambientStrength * lightColor;//散射因子,也就是两个方向夹角的cos值vec3 norm = normalize(Normal);vec3 lightDir = normalize(lightPos - FragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = diff * lightColor;vec3 result = (ambient + diffuse) * objectColor;     //增加一个散射因子FragColor = vec4(result, 1.0);
}

CPU端也要进行相应的修改:

     Shader colorShader("../Shader/shader_basic_lighting.vs", "../Shader/shader_basic_lighting.fs");Shader cubeShader("../Shader/shader_light_cube.vs", "../Shader/shader_light_cube.fs");//顶点数据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 colorVAO, VBO;glGenVertexArrays(1, &colorVAO);glBindVertexArray(colorVAO);glGenBuffers(1, &VBO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));glEnableVertexAttribArray(1);unsigned int cubeVAO;glGenVertexArrays(1, &cubeVAO);glBindVertexArray(cubeVAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);//光源的位置glm::vec3 lightPos(1.2f, 1.0f, 2.0f);while (!glfwWindowShouldClose(window)) {float currentFrame = glfwGetTime();deltaTime = currentFrame - lastFrame;lastFrame = currentFrame;glEnable(GL_DEPTH_TEST);processInput(window);glClearColor(0.1f, 0.1f, 0.1f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glm::mat4 model = glm::mat4(1.0f);glm::mat4 view = glm::mat4(1.0f);glm::mat4 projection = glm::mat4(1.0f);//绘制有颜色的立方体colorShader.use();colorShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f);colorShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f);colorShader.setVec3("lightPos", lightPos);projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);view = camera.GetViewMatrix();colorShader.setMat4("projection", projection);colorShader.setMat4("view", view);colorShader.setMat4("model", model);glBindVertexArray(colorVAO);glDrawArrays(GL_TRIANGLES, 0, 36);cubeShader.use();//view = glm::translate(view, glm::vec3(0.0f, 0.0f, -10.0f));//view = glm::lookAt(glm::vec3(0.0f, 0.0f, 10.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));cubeShader.setMat4("projection", projection);cubeShader.setMat4("view", view);model = glm::mat4(1.0f);model = glm::translate(model, lightPos);        //将灯平移到lightPos位置model = glm::scale(model, glm::vec3(0.2f));       //并对其进行一定程度的缩放cubeShader.setMat4("model", model);glBindVertexArray(cubeVAO);glDrawArrays(GL_TRIANGLES, 0, 36);glfwSwapBuffers(window);glfwPollEvents();}

运行效果:

2.3镜面光照

现实生活中,我们无论在哪一个位置去观测一个表面相对光滑的物体,都会感觉这个物体相较于一些粗糙的物体更亮。其中这主要的原因就是因为镜面光的作用,因此考虑到这一点,冯氏光照模型中通过引入反射向量与人眼视线方向的夹角这一数值因子,来更好的模拟现实中光照对物体颜色的影响,实现过程如下所示。

shader_basic_lighting2.vs

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) 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);
}

shader_basic_lighting2.fs

#version 330 core
out vec4 FragColor;in vec3 Normal;
in vec3 FragPos;  uniform vec3 lightPos;
uniform vec3 viewPos;
uniform vec3 lightColor;
uniform vec3 objectColor;void main()
{//环境光float ambientStrength = 0.1;vec3 ambient = ambientStrength * lightColor;//散射光 vec3 norm = normalize(Normal);vec3 lightDir = normalize(lightPos - FragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = diff * lightColor;//镜面光float specularStrength = 0.5;   //设置镜面光的强度vec3 viewDir = normalize(viewPos - FragPos); //视线方向vec3 reflectDir = reflect(-lightDir, norm);  //第一个参数是指从光源指向片段位置的向量float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); //32是高光的发光值,可以认为是一个物体的反射光的能力vec3 specular = specularStrength * spec * lightColor;   //计算出镜面光的最终结果vec3 result = (ambient + diffuse + specular) * objectColor;FragColor = vec4(result, 1.0);
}

为了效果可以好一些,我特意修改了一下,光源与相机的位置:

Camera camera(glm::vec3(-4.0f,2.0f, 5.0f));
glm::vec3 lightPos(1.2f, 1.0f, -2.0f);

最后再将相机的位置传递给着色器即可。

colorShader.setVec3(“viewPos”, camera.Position); //将相机位置(人眼位置)传递给着色器

运行效果:

参考资料:《Learning OpenGL》

OpenGL学习笔记——光照(一)相关推荐

  1. 【OpenGL学习笔记⑧】——键盘控制正方体+光源【冯氏光照模型 光照原理 环境光照+漫反射光照+镜面光照】

    ✅ 重点参考了 LearnOpenGL CN 的内容,但大部分知识内容,小编已作改写,以方便读者理解. 文章目录 零. 成果预览图 一. 光照原理与投光物的配置 1.1 光照原理 1.2 投光物 二. ...

  2. OpenGL学习笔记:矩阵变换

    文章目录 缩放 glm矩阵表示 glm缩放矩阵实现 位移 齐次坐标 glm位移矩阵实现 旋转 沿x轴旋转 沿y轴旋转 沿z轴旋转 沿任意轴旋转 glm旋转矩阵实现 矩阵的组合 glm矩阵组合使用 接上 ...

  3. OpenGL学习笔记(一)绘制点线面及多面体

    OpenGL学习笔记(一)绘制点线面及多面体 绘制点线面 #include <iostream> #include <GL/GLUT.h> #define PI 3.14159 ...

  4. OpenGL学习笔记(一):环境搭建、三维空间坐标系理解以及OpenGL的基本使用

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7866 ...

  5. OPENGL学习笔记之八

    OPENGL学习笔记之八 2017/11/15 阅读材料来自learnopengl.com以及learnopengl-cn.github.io 我们通常会自己设定一个坐标的范围,之后再在顶点着色器中将 ...

  6. 【OpenGL学习笔记】地月系

    OpenGL学习笔记2-地月系 文章目录 OpenGL学习笔记2-地月系 前言 运行结果 纹理图片 一.TexturePool 1.**TexturePool.h** 2.**TexturePool. ...

  7. 【OpenGL学习笔记⑥】——3D变换【旋转的正方体 实现地月系统 旋转+平移+缩放】

    ✈️ 文章目录 零. 成果预览图 一.3D立方体的顶点数组 二.纹理旋转 三.纹理缩放 四.画n个3D图形 五.轨道的数学公式 六.深度缓冲(Z 缓冲) 七.完整代码 八.参考附录: 神器的正方体 ☁ ...

  8. OpenGL 学习笔记 II:初始化 API,第一个黑窗,游戏循环和帧率,OpenGL 默认垂直同步,glfw 帧率

    前情提要: 上一篇: OpenGL 学习笔记 I:OpenGL glew glad glfw glut 的关系,OpenGL 状态机,现代操作系统的窗口管理器,OpenGL 窗口和上下文 OpenGL ...

  9. OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7888 ...

最新文章

  1. Oracle RMAN 还原与恢复(一)--还原服务器参数文件
  2. ABAP更改程序的请求包操作
  3. 电脑实用mysql后C盘内存不足_电脑高手用这方法,终于解决了C盘空间不足的问题,网友:这操作服了...
  4. 并查集判断是否有环存在
  5. 为什么线程池里的方法会执行两次_面试官问你java都有哪些线程池,自己是否自定义过线程池...
  6. leetcode881. 救生艇(贪心算法加双指针)
  7. 每日一题(易错):这条SQL语句,有什么作用?
  8. Dart获取系统和硬件信息
  9. 给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。
  10. Spark的基本工作流程
  11. ckfinder的使用
  12. The server encountered an internal error that prevented it from fulfilling this request. exception
  13. e4a 安卓获取ROOT权限的方法思路 转载
  14. javascript学习-SVG
  15. dlt645协议电表数据采集接入PLC或scada等组态软件系统(转modbus)实现内网监控技术方案
  16. Cartographer的CSM理解
  17. 微信对账单--每日定时任务获取昨日微信支付账单
  18. ZUCC_操作系统原理实验_实验九 消息队列
  19. 机器学习中,什么是预测性维护,常见技术有哪些
  20. 使用软件starf**k_de(更新0.82b版本),免拔光驱线玩YS6

热门文章

  1. IntellJ IDEA 基础之 一些常用插件plugin 简单整理 (辅助提高编写代码效率)
  2. QQWRY应用:ASP.NET捕获客户机IP和物理地址
  3. 投资4万元开一家定制个性手表工作室
  4. 无主之地3mod热修工具用法
  5. URLScheme唤醒App
  6. 牛叉的 erlang
  7. index of rmvb mp3 rm突破站点入口下载
  8. 什么是源文件什么是头文件_那是什么文件
  9. 1、Denoising Diffusion Probabilistic Models(扩散模型)
  10. 如何使用photoshop将论文数据图中的英文变成中文