shader学习笔记一:shader运行原理及uniform关键字

2023-11-17

shader运行原理

  首先,opengl api函数输入一些数据,包括顶点数据、纹理数据、矩阵变换数据,这些顶点数据到"顶点处理阶段"。

  “顶点处理阶段”: 图形流水线会调用 vertex shader(顶点shader),对顶点进行处理,有多少个顶点就调用多少次vertex shader 程序。vertex shader主要做的工作是顶点变换(旋转,缩放,平移)、观察变换、投影变换、视口变换,最终把三维的顶点转换为二维的顶点。
  顶点处理完后, 图形流水线走向图元装配、光栅化、片元处理阶段。
  “片元处理阶段” :将对像素颜色进行处理,有多少个像素就调用多少次Fragment shader 程序。

总结:Fragment shader 程序执行次数往往远远多于vertex shader 程序,所以Fragment shader 程序对效率影响很大。

在这里插入图片描述

uniform变量

uniform修饰符,在shader中理解为全局变量

使用函数

shader程序 
uniform vec4 _color;
....

GLint _colorID = glGetUniformLocation(_program, "_color"); //获取shader中的uniform vec4 _color 地址,即建立shader中的变量和程序中变量关联
....

glUniform4f(_colorID, 0, 1, 0, 1); //通过_colorID 改变对应的shader中 _color 的值

程序代码

shader.hpp

#pragma once

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <GL/glew.h>

using namespace std;

class Shader
{
public:
	//传入的要么是shader路径,要么是code
	Shader(const string vertexstr, const string fragmentstr, bool isCode = false);

	int getShaderProgram();

	// begin end之间就是这个shader程序的作用域
	// 使用shader
	void begin();
	// 结束
	void end();

	//获取uniform 变量地址
	GLint getUniformLocation(string attName);

private:
	GLuint _program;
};

shader.cpp

#include "shader.hpp"

//根据shader 源文件 初始化
Shader::Shader(const string vertexstr, const string fragmentstr, bool isCode) {
	string vertexCode;
	string fragmentCode;

	if(isCode) {
		vertexCode = vertexstr;
		fragmentCode = fragmentstr;
	}
	else {
		ifstream vShaderFile;
		ifstream fShaderFile;
		vShaderFile.exceptions(std::ifstream::badbit);
		fShaderFile.exceptions(std::ifstream::badbit);
		try {
			vShaderFile.open(vertexstr);
			fShaderFile.open(fragmentstr);
			std::stringstream vShaderStream, fShaderStream;
			vShaderStream << vShaderFile.rdbuf();
			fShaderStream << fShaderFile.rdbuf();
			vShaderFile.close();
			fShaderFile.close();
			vertexCode = vShaderStream.str();
			fragmentCode = fShaderStream.str();
		}
		catch(std::ifstream::failure e) {
			cout << "读取失败" << endl;
		}
	}
	const GLchar* vShaderCode = vertexCode.c_str();
	const GLchar * fShaderCode = fragmentCode.c_str();
	GLuint vertex, fragment;
	GLint success;
	GLchar infoLog[512];
	// 1. 创建一个顶点shader对象
	vertex = glCreateShader(GL_VERTEX_SHADER);
	// 给shader vertex对象 指定源代码
	glShaderSource(vertex, 1, &vShaderCode, NULL);
	// 2. 编译shader
	glCompileShader(vertex);
	// 获取编译状态
	glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
	if(!success) {
		//编译失败 下面获取编译日志
		glGetShaderInfoLog(vertex, 512, NULL, infoLog);
		cout << "顶点着色器编译错误: " << infoLog << endl;
	}
	// 3. 创建一个像素shader对象
	fragment = glCreateShader(GL_FRAGMENT_SHADER);
	// 给shader fragment对象 指定源代码
	glShaderSource(fragment, 1, &fShaderCode, NULL);
	// 4. 编译shader
	glCompileShader(fragment);
	// 获取编译状态
	glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
	if(!success) {
		//编译失败 下面获取编译日志
		glGetShaderInfoLog(fragment, 512, NULL, infoLog);
		cout << "片元着色器编译错误:" << infoLog << std::endl;
	}
	// 5. 创建程序
	this->_program = glCreateProgram();
	// 把编译好的shader对象加入程序中
	glAttachShader(this->_program, vertex);
	glAttachShader(this->_program, fragment);
	// 6. 链接程序
	glLinkProgram(this->_program);

	//获取链接状态
	glGetProgramiv(this->_program, GL_LINK_STATUS, &success);
	if(!success) {
		//链接失败 下面获取链接日志
		glGetProgramInfoLog(this->_program, 512, NULL, infoLog);
		cout << "链接失败: " << infoLog << std::endl;
	}

	// 删除着色器对象
	glDeleteShader(vertex);
	glDeleteShader(fragment);
}

int Shader::getShaderProgram() {
	return this->_program;
}

//使用
void Shader::begin() {
	//使用shader程序
	glUseProgram(this->_program);
}

void Shader::end() {
	glUseProgram(0);
}

GLint Shader::getUniformLocation(string attName) {
	return glGetUniformLocation(_program, attName.c_str());
}

main.cpp


/*
*
* 该实例演示shader程序的使用,及uniform变量在程序中赋值
*
*/

#define GLEW_STATIC
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <glm/vec3.hpp> // glm::vec3
#include <glm/vec4.hpp> // glm::vec4
#include <glm/mat4x4.hpp> // glm::mat4
#include <glm/ext/matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale
#include <glm/ext/matrix_clip_space.hpp>

#include "FreeImage.h"

#include "shader.hpp"

#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )  //这行是取消显示控制台

char szTitle[64] = "opengl view";


//glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);//创建一个点
//glm::mat4 trans = glm::mat4(1.0f);//创建单位矩阵
//Window dimensions    
const GLuint WIDTH = 800, HEIGHT = 600;

GLfloat ratio = 1.f;
GLfloat xpos, ypos;

glm::vec3 _eye(0, 0, 10);
glm::vec3 _lookAt(0, 0, 0);
glm::vec3 _up(0, 1, 0);

glm::mat4 _matProj = glm::mat4(1.0f);//创建单位矩阵
glm::mat4 _matView = glm::mat4(1.0f);//创建单位矩阵


float size = 100.0f;

//顶点数据
struct Vertex {
	float x, y, z;
	float u, v;
};

Vertex g_cubeVertices[] =
{
	{ -1.0f, -1.0f, 1.0f, 0.0f, 0.0f },
	{ 1.0f, -1.0f, 1.0f, 1.0f, 0.0f },
	{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
	{ -1.0f, 1.0f, 1.0f, 0.0f, 1.0f },

	{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f },
	{ -1.0f, 1.0f, -1.0f, 1.0f, 1.0f },
	{ 1.0f, 1.0f, -1.0f, 0.0f, 1.0f },
	{ 1.0f, -1.0f, -1.0f, 0.0f, 0.0f },

	{ -1.0f, 1.0f, -1.0f, 0.0f, 1.0f },
	{ -1.0f, 1.0f, 1.0f, 0.0f, 0.0f },
	{ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f },
	{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f },

	{ -1.0f, -1.0f, -1.0f, 1.0f, 1.0f },
	{ 1.0f, -1.0f, -1.0f, 0.0f, 1.0f },
	{ 1.0f, -1.0f, 1.0f, 0.0f, 0.0f },
	{ -1.0f, -1.0f, 1.0f, 1.0f, 0.0f },

	{ 1.0f, -1.0f, -1.0f, 1.0f, 0.0f },
	{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f },
	{ 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
	{ 1.0f, -1.0f, 1.0f, 0.0f, 0.0f },

	{ -1.0f, -1.0f, -1.0f, 0.0f, 0.0f },
	{ -1.0f, -1.0f, 1.0f, 1.0f, 0.0f },
	{ -1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
	{ -1.0f, 1.0f, -1.0f, 0.0f, 1.0f },

	// 地面数据
	{ -size, -1.0f, -size, 0.0f, 0.0f },
	{ -size, -1.0f, size, 100.0f, 0.0f },
	{ size, -1.0f, size, 100.0f, 100.0f },
	{ size, 0.0f, -size, 0.0f, 100.0f }
};

//纹理ID
GLuint  _texture;
GLuint  _vbo;

//地面纹理
GLuint  _texGround;

Shader* _shader = nullptr;


static void error_callback(int error, const char* description) {
	fputs(description, stderr);
}

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
	std::cout << "key " << key << std::endl;

	switch(key) {
		case GLFW_KEY_ESCAPE:
			glfwSetWindowShouldClose(window, GL_TRUE);
			break;
		case GLFW_KEY_UP:
			_eye.z  -=  0.1f;   //这里修改摄像机参数
			break;
		case GLFW_KEY_DOWN:
			_eye.z  +=  0.1f;
			break;
		case GLFW_KEY_RIGHT:
			_eye.x  -=  1.0f;
			break;
		case GLFW_KEY_LEFT:
			_eye.x  +=  1.0f;
			break;

		default:
			break;
	}
}

static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
	if(action != GLFW_PRESS)
		return;

	switch(button) {
		case GLFW_MOUSE_BUTTON_LEFT:
			std::cout << "Mosue left button clicked!" << std::endl;
			break;
		case GLFW_MOUSE_BUTTON_MIDDLE:
			std::cout << "Mosue middle button clicked!" << std::endl;
			break;
		case GLFW_MOUSE_BUTTON_RIGHT:
			std::cout << "Mosue right button clicked!" << std::endl;
			break;
		default:
			return;
	}
	return;
}

static void cursor_position_callback(GLFWwindow* window, double x, double y) {
	//std::cout << "Mouse position move to X: " << x << " Y: " << y << std::endl;
	xpos = float((x - WIDTH / 2) / WIDTH) * 2;
	ypos = float(0 - (y - HEIGHT / 2) / HEIGHT) * 2;
	return;
}

static void scroll_callback(GLFWwindow* window, double x, double y) {
	return;
}

static unsigned createTexture(int w, int h, const void* data, GLenum type) {
	unsigned    texId;
	glGenTextures(1, &texId);
	glBindTexture(GL_TEXTURE_2D, texId);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	glTexImage2D(GL_TEXTURE_2D, 0, type, w, h, 0, type, GL_UNSIGNED_BYTE, data);

	return  texId;
}
/**
*   使用FreeImage加载图片
*/
static unsigned createTextureFromImage(const char* fileName) {
	//1 获取图片格式
	FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);
	if(fifmt == FIF_UNKNOWN) {
		return  0;
	}
	//2 加载图片
	FIBITMAP    *dib = FreeImage_Load(fifmt, fileName, 0);

	FREE_IMAGE_COLOR_TYPE type = FreeImage_GetColorType(dib);

	//3 获取数据指针
	FIBITMAP*   temp = dib;
	dib = FreeImage_ConvertTo32Bits(dib);
	FreeImage_Unload(temp);

	BYTE*   pixels = (BYTE*)FreeImage_GetBits(dib);
	int     width = FreeImage_GetWidth(dib);
	int     height = FreeImage_GetHeight(dib);

	for(int i = 0; i < width * height * 4; i += 4) {
		BYTE temp = pixels[i];
		pixels[i] = pixels[i + 2];
		pixels[i + 2] = temp;
	}

	unsigned    res = createTexture(width, height, pixels, GL_RGBA);
	FreeImage_Unload(dib);
	return      res;
}

static GLint _colorID;

static void onInit() {
	_texture    =   createTextureFromImage("../res/1.jpg");
	_texGround  =   createTextureFromImage("../res/dimian.jpg");

	glGenBuffers(1, &_vbo);
	glBindBuffer(GL_ARRAY_BUFFER, _vbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(g_cubeVertices), g_cubeVertices, GL_STATIC_DRAW);
	glBindBuffer(GL_ARRAY_BUFFER, 0);


	string vsCode = "void main()\
					{\
					    gl_Position = ftransform();\
					}";

	string psCode = "uniform vec4 _color; \
					void main()\
					{\
					    gl_FragColor = _color;\
					}";

    //uniform 理解为shader程序中的全局变量

	//gl_Position 内置变量 表示输出顶点
	//gl_FragColor 内置变量 表示输出颜色

	//ftransform() 内置函数

	//_shader = new Shader("../res/shader/vertShader1.vert", "../res/shader/fragShader1.frag");

	_shader = new Shader(vsCode, psCode, true);

	//获取shader中的uniform vec4 _color 地址,即建立shader中的变量和程序中变量关联
	_colorID  =   _shader->getUniformLocation("_color");
}

static void onDestory() {
	glDeleteTextures(1, &_texture);
	glDeleteTextures(1, &_texGround);
	glDeleteBuffers(1, &_vbo);   //删除VBO 显存中释放VBO内存
}

// 绘制
static void render(GLFWwindow * window) {

	glClearColor(0, 0, 0, 1);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glEnable(GL_DEPTH_TEST);
	glEnable(GL_TEXTURE_2D);

	glMatrixMode(GL_MODELVIEW);
	_matView = glm::lookAt(_eye, _lookAt, _up); //使用glm数学库 根据公式计算得到视图矩阵  这公式可以推倒出来

	//摄像机围绕目标旋转
	static float angle = 0; //旋转角度
	float r = 10;           //旋转半径
	_eye.x = cos(angle * glm::pi<double>() / 180) * r;
	_eye.z = sin(angle * glm::pi<double>() / 180) * r;
	angle += 1;  //角度每帧加一

	glm::mat4 matVP = _matProj * _matView;
	glLoadMatrixf(&matVP[0][0]);

	
	glBindTexture(GL_TEXTURE_2D, _texture);

	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	//开始使用ID为 _vbo  的buffer 接下来的操作针对这个VBO
	glBindBuffer(GL_ARRAY_BUFFER, _vbo);

	float* addrVertex = (float*)0;
	float* uvAddress = (float*)12;

	glVertexPointer(3, GL_FLOAT, sizeof(Vertex), addrVertex);
	glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), uvAddress);

	// 绘制 立方体
	_shader->begin(); //使用 shader 对绘制立方体起作用

	//先begin 使用这个shader 然后才能修改
	glUniform4f(_colorID, 0, 1, 0, 1); //通过_colorID 改变对应的shader中 _color 的值

	glDrawArrays(GL_QUADS, 0, 24);   //shader 只在针对 glDrawArrays 这类绘制函数其作用,顶点处理阶段调用顶点shader 光栅化处理阶段调用片元shader
	_shader->end();   //结束  如果不掉用这个函数 glUseProgram设置为0,这个shader程序会对后面的绘制产生影响

	//绘制地面
	//glLoadIdentity(); //这里打开 地面就不会跟着旋转 说明摄像机操作的是模型矩阵
	glBindTexture(GL_TEXTURE_2D, _texGround);
	glDrawArrays(GL_QUADS, 24, 4);


	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glBindTexture(GL_TEXTURE_2D, 0);
	glfwSwapBuffers(window);
	glfwPollEvents();
}

int main(void) {
	GLFWwindow * window;

	glfwSetErrorCallback(error_callback);

	if(!glfwInit())
		return -1;

	window = glfwCreateWindow(WIDTH, HEIGHT, szTitle, NULL, NULL);
	if(!window) {
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	glfwSetKeyCallback(window, key_callback);
	glfwSetMouseButtonCallback(window, mouse_button_callback);
	glfwSetCursorPosCallback(window, cursor_position_callback);
	glfwSetScrollCallback(window, scroll_callback);

	glfwMakeContextCurrent(window);

	glewExperimental = GL_TRUE;
	glewInit();
	onInit();
	glViewport(0, 0, WIDTH, HEIGHT); //设置opengl视口 即看到的显示区域

	_matProj = glm::perspective(glm::radians(60.0f), float(WIDTH) / float(HEIGHT), 0.1f, 1000.0f);//使用glm数学库 根据公式计算得到投影矩阵  这公式可以推倒出来

	while(!glfwWindowShouldClose(window)) {
		render(window);
	}

	onDestory();
	glfwDestroyWindow(window);

	glfwTerminate();
	return 0;
}

运行结果

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

shader学习笔记一:shader运行原理及uniform关键字 的相关文章

  • Data->Iopb->Parameters.Create.Options & FILE_DIRECTORY_FILE 判断是否为路径

    如何在minifilter 判断操作的文件对象是目录还是文件呢 有很多人发现答案是 Data gt Iopb gt Parameters Create Options FILE DIRECTORY FILE 是否成立 不过也有很多人发现 上
  • centos7 nginx 配置 ssl证书

    安装nginx 从阿里云服务器下载 nginx版本的ssl证书 防止再 etc nginx ssl 下 停止 nginx 服务 systemctl stop nginx 修改配置文件 etc nginx conf d root izm5ej
  • app离线消息推送服务器,在线消息推送和离线消息推送(3)

    首先介绍一下具体的功能设计 整个系统由服务端 客户端组成 客户端包含前端 浏览器端 pyqt桌面端 和后台 用于添加要推送的消息 因为浏览器端不容易注意到实时提醒 所以我将实时提醒功能放到pyqt桌面端中实现 如托盘区闪烁等醒目的方式 浏览
  • Unity 数据保存失败

    问题 游戏数据突然保存不了了 没有任何报错 切后台保存也出问题 编辑器上和PC端没问题 移动端上保存不了 原因 我使用的存储方式是 Newtonsoft Json 将对象转换成加密字符串并保存到本地 而不巧的是 我使用了 HashSet 这
  • BOOST升压电路原理详解

    原文来自公众号 工程师看海 BOOST升压电源是利用开关管开通和关断的时间比率 维持稳定输出的一种开关电源 它以小型 轻量和高效率的特点被广泛应用在各行业电子设备找那个 是不可缺少的一种电源架构 公众号后台回复 boost仿真文件 Boos
  • Linux 添加开机启动方法

    添加开启启动的方式一般有如下几种 第一种 把开机命令 写入到os的启动文件之中 伴随着启动文件的读取 顺便帮你把要启动的任务 一起启动了 第二种 把启动任务 放到os的启动目录下 os启动过程之中 会执行所有放在此目录下的任务 第三种 os
  • KaTeX数学公式输入

    序号 运算符 输入 举例 举例代码 1 x y
  • 【Java 学习】方法 和 一些编程案例

    文章目录 一 概述 二 案例 1 计算1 n的和返回 2 判断整数是奇数还是偶数 3 数组求最值改方法实现 三 方法的内存原理 四 方法参数传递机制 基本类型 引用类型 五 参数传递的案例 1 打印整型数组内容 2 从数组中查询指定元素的索
  • 【机器学习】SMO算法

    1 SMO基础概念 将原始最优化问题转化成了其对偶问题 因为对偶问题是一个凸二次规划问题 这样的凸二次规划问题具有全局最优解 其中 xi yi xi yi 表示训练样本数据 xixi为样本特征 yi 1 1 yi 1 1 为样本标签 C为惩
  • 中国货币超发严重 去年新增货币占全球近一半

    提要 2009年以来 中国已成为目前全球最大的 印钞机 2012年 全球新增货币供应量中国占近一半 21世纪网评估发现 均衡人均收入差异后 中国的经济货币化程度高居全球前列 截至2012年末 中国M2余额达到人民币97 42万亿元 居世界第
  • JS考点

    JavaScript 1 原始值和引用值类型及区别 原始值即存在栈中的数据 包含symbol number string null undefined boolean类型 引用值即存在堆中的对象 对象地址 指针 存在栈中 指向堆中存储的数据
  • 2021-07-25

    神经网络 M P神经元 感知机 感知机 神经网络 M P神经元 1 M P神经元 模拟生物行为的数学模型 接手n个输入 来自其他的神经元 并给各个输入赋予权重计算加权和 再跟自己特有的阀值 比较 通常用减法 最后经过激活函数 模拟 抑制 和
  • Stable Diffusion Base Model from safetensors transfer to diffusers

    Steps File Setup Clone the ControlNet model repo from HF into a folder like hf controlnet model git clone https huggingf
  • Qt 中父子关系使用总结

    背景 Qt 中到父子关系和类的继承无关 仅表示对象间到从属关系 继承自 QObject 的对象在构造时需要指定父对象指针 include
  • 计算机基础知识+Java语言基础 +JAVA学习笔记-DAY01

    计算机基础知识 01 01 计算机概述 了解 A 什么是计算机 计算机在生活中的应用举例 计算机 Computer 全称 电子计算机 俗称电脑 是一种能够按照程序运行 自动 高速处理海量数据的现代化智能电子设备 由硬件和软件所组成 没有安装
  • Cent OS6.5 安装nodeJS(分分钟搞定)

    第一步 下载 cd opt wget https nodejs org dist v7 5 0 node v7 5 0 linux x64 tar xz 第二步 解压缩文件包 xz d node v7 5 0 linux x64 tar x
  • hive原理与源码分析-hive源码架构与理论(一)

    什么是Hive 数据仓库 存储 查询 分析大规模数据 SQL语言 简单易用的类SQL查询语言 编程模型 允许开发者自定义UDF Transform Mapper Reducer 来更简单地完成复杂MapReduce无法完成的工作 数据格式
  • 运放增加输出电流

    功率输出模块 采用三极管9012 9013来进行双向扩流以提高其带载能力 可以完全满足发挥部分所要求的稳幅输出能力 当负载变化时 其输出电压幅度变化小于3 如图所示 集成运放的扩流和扩压 一 集成运放的扩流 在集成运放的输出端再加一级互补对
  • k8s-client(java)从6.0.1升级到11.0.0出现patch问题may not be specified for non-apply patch/cannot unmarshal...

    背景 kubernetes client java升级 复杂的patch出现各种问题 并且没有找到解决方案 经过研究 测试 找到了解决方案 希望能帮助到使用kubernetes client java客户端的同学 patch方法调用出现异常

随机推荐

  • IEEE 1471(ISO/IEC/IEEE 42010)架构描述方法

    ISO IEC IEEE 42010 架构描述方法 关于 背景 架构描述 利益相关者和关注点 架构视图和架构观点 架构模型 架构关系 架构原理 关于 本文对软件体系架构的描述方法的研究基于 ISO IEC IEEE 42010 ISO IE
  • unity ethan_响应式网页设计的挑战,Ethan Marcotte

    unity ethan In this episode of the Versioning Show David and Tim are joined by Ethan Marcotte a well known designer who
  • c语言设计(TVI)地铁自动售票机---@颜麓

    设计TVI 地铁自动售票机 机软件 输入站数 计算费用 计费规则 6站2元 7 10站3元 11站以上为4元 输入钱数 计算找零 找零时优先找回面额大的钞票 找零方式为各种面额张数 可识别面额 100 50 20 10 5 1 includ
  • Sentinel整合Ribbon/OpenFeign,Sentinel自定义限流熔断

    Sentinel服务熔断环境搭建 服务熔断 应对微服务雪崩效应的一种链路保护机制 类似保险丝 需要完成Sentinel整合Ribbon openFeign 所以我们先要搭建环境 那么先从整合Ribbon开始 环境搭建 为了演示操作 所以在这
  • DBeaver改成英语

    DBeaver改成英语 安装目录中有个dbeaver ini文件 追加 Duser language en可以改回英文 有些数据库术语翻译后反而不太容易理解
  • java获取唯一时间戳Id.多线程保证唯一性

    工程里有获取唯一时间戳作为id的需求 想了想用乐观锁cas实现 自旋 cas原子性操作获得了绝对唯一的时间戳 系统时间 纳秒版本 单机有效 不能分布式调用 public class AtomicTimeStamp private Atomi
  • Anaconda的安装与环境配置

    这里简单的记录一下Anaconda的安装过程 没有干货 只是记录 但也看了就会 下载安装包 这里有两个下载地址 分别是官网和清华镜像源 推荐清华镜像 下的快 官网下半天还可能失败 无论是哪个下载地址 找到对应你系统的安装程序下载即可 官网
  • Ubuntu下安装JDK图文教程详解

    操作系统 Ubuntu 11 10 我们选择的是jdk1 6 0 30版本 安装文件名为jdk 6u30 linux i586 bin 1 复制jdk到安装目录 1 假设jdk安装文件在桌面 我们指定的安装目录是 usr local jav
  • 可以编辑的table antd

    版本一 效果图 有保存按钮 antd3 代码 import React Component from react import Form Input Button Table Divider Popconfirm Tooltip from
  • 19_复制目录下所有文件夹和目录CopyFile()

    复制目录下所有文件夹和目录CopyFile 想一下 若要复制文件夹 可以在目录位置新建一个文件夹 然后将源文件夹中里面的文件进行遍历 一个一个的复制到目标文件夹中即可 void EnumCopyFile 输入参数 TCHAR szSrcRo
  • STL——vector以及emplace_back分析

    1 这里需要注意凡是连续空间的容器都提供operator 是为了数组操作 2 back 应该是 end 1 3 vector的大小为12 vector的迭代器为指针 1 emplace back 1 相比push back 如果传入临时对象
  • matlab中的锐度测量,锐度(解析度)MTF定义及测试

    Image sharpness 图像锐度 解析度 锐度无疑是最重要的摄影图像质量的评价因素 它是关系到图片中有多少细节可以被辨认的最密切因素 但它不是唯一的重要因素 其他重要因素包括色差 与锐度密切相关 噪音 动态范围 与噪声密切相关 和色
  • mysql常用命令

    mysql命令 查询 限制返回个数及偏移量 m 偏移量 n 个数 只限制个数可省略m 如limit 2 select from
  • IntelliJ IDEA破解

    今天写个IDEA破解 废话不多说 直接给网址 官网 https www jetbrains com idea 破解注册码 http idea lanyus com 里面有永久破解 还有注册码 可你根据你的喜爱 来选择 今天写一下它的破解补丁
  • HashMap之扩容原理

    一 什么是HashMap HashMap 数据结构为 数组 链表 JDk1 7 JDK1 8中增加了红黑树 其中 链表的节点存储的是一个 Entry 对象 每个Entry 对象存储四个属性 hash key value next 二 为什么
  • explicit关键字解析

    C 提供了关键字explicit 可以阻止不应该允许的经过转换构造函数进行的隐式转换的发生 声明为explicit的构造函数不能在隐式转换中使用 C 中 一个参数的构造函数 或者除了第一个参数外其余参数都有默认值的多参构造函数 承担了两个角
  • Vue3.0-计算属性computed

    Vue3 0中的computed的功能与2 0中的计算函数功能一样 引入方法 import computed from vue 使用 在引入之后 设计箭头函数 var name computed gt 函数体 retrun 返回值 也就是计
  • Make和Makefile快速入门

    文章目录 目的 基础入门 Makefile语法 基础杂项 变量 条件选择 函数 文件引用 嵌套执行 make使用 使用进阶 总结 目的 我们可以在终端中通过命令来使用GCC编译代码生成可执行文件 对于实际的项目因为涉及的文件通常会比较多一些
  • 搭建OpenGL开发环境

    资料 安装教程 软件下载 Visual Studio 2019 CMake GLFW GLAD glfw 3 3 8 下载glfw的目的 获取压缩包里的include 生成glfw3 lib 获取include 解压找到Include in
  • shader学习笔记一:shader运行原理及uniform关键字

    shader运行原理 首先 opengl api函数输入一些数据 包括顶点数据 纹理数据 矩阵变换数据 这些顶点数据到 顶点处理阶段 顶点处理阶段 图形流水线会调用 vertex shader 顶点shader 对顶点进行处理 有多少个顶点