使用OpenGL 立方体贴图

2023-11-09

openGL系列文章目录

前言

对于室外3D 场景,通常可以通过在地平线上创造一些逼真的效果,来增强其真实感。
当我们极目远眺,目光越过附近的建筑和森林,我们习惯于看到远处的大型物体,例如:
云、群山或太阳(或夜空中的星星和月亮)。但是,将这些对象作为单个模型添加到场景中
可能会产生高到无法承受的性能成本。天空盒或天空穹顶提供了有效且相对简单的方法,
用来生成令人信服的地平线景观。

一、OpenGL 立方体贴图

构建天空盒的另一种方法是使用OpenGL 纹理立方体贴图。OpenGL 立方体贴图比我们
在上一节中看到的简单方法稍微复杂一点。但是,使用OpenGL 立方体贴图有自己的优点,
例如减少接缝以及支持环境贴图。
OpenGL 纹理立方体贴图类似于稍后将要研究的3D 纹理,它们都使用3 个纹理坐标访
问——通常标记为(s, t, r)——而不是我们目前为止用到的两个。OpenGL 纹理立方体贴图
的另一个特性是,其中的图像以纹理图像的左上角(而不是通常的左下角)作为纹理坐标
(0, 0, 0),这通常是混乱产生的源头。
程序9.1 中展示的方法通过读入单个图像来为立方体贴图添加纹理,而程序9.2 中展示
的loadCubeMap()函数则读入6 个单独的立方体面图像文件。正如我们在第5 章中所学的,
有许多方法可以读取纹理图像,我们选择使用SOIL2 库。在这里,SOIL2 用于实例化和加
载OpenGL 立方体贴图也非常方便。我们先找到需要读入的文件, 然后调用
SOIL_load_OGL_cubemap(),其参数包括6 个图像文件和一些其他参数,类似于我们在第5
章中看到的SOIL_load_OGL_texture()。在使用OpenGL 立方体贴图时,无须垂直翻转纹理,
OpenGL 会自动进行处理,注意,loadCubeMap()函数放在“Utils.cpp”文件中。
init()函数现在包含一个函数调用以启用GL_TEXTURE_CUBE_MAP_SEAMLESS,它告
诉OpenGL 尝试混合立方体相邻的边以减少或消除接缝。在display()中,立方体的顶点像以
前一样沿管线向下发送,但这次不需要发送立方体的纹理坐标。我们将会看到,OpenGL 纹
理立方体贴图通常使用立方体的顶点位置作为其纹理坐标。之后禁用深度测试并绘制立方
体。然后为场景的其余部分重新启用深度测试。
完成后的OpenGL 纹理立方体贴图使用了int 类型的标识符进行引用。与阴影贴图时一
样,通过将纹理包裹模式设置为“夹紧到边缘”,可以减少沿边框的伪影。在这种情况下,
它还可以帮助进一步缩小接缝。请注意,这里需要为3 个纹理坐标s、t 和r 都设置纹理包
裹模式。
在片段着色器中使用名为samplerCube 的特殊类型的采样器访问纹理。在纹理立方体贴
图中,从采样器返回的值是沿着方向向量(s, t, r)从原点“看到”的纹素。因此,我们通常可
以简单地使用传入的插值顶点位置作为纹理坐标。在顶点着色器中,我们将立方体顶点位
置分配到输出纹理坐标属性中,以便在它们到达片段着色器时进行插值。另外需要注意,
在顶点着色器中,我们将传入的视图矩阵转换为3×3,然后再转换回4×4。这个“技巧”
有效地移除了平移分量,同时保留了旋转(回想一下,平移值在转换矩阵的第四列中)。这
样,就将立方体贴图固定在了摄像机位置,同时仍允许合成相机“环顾四周”。

二、使用步骤

1.代码

#include "glew/glew.h"
#include "glfw/glfw3.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
#include "camera.h"
#include "Utils.h"
#include "Torus.h"
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

static const float pai = 3.1415926f;
float toRadians(float degrees) { return degrees * 2.f * pai / (float)360.f; }

static const int screenWidth = 1920;
static const int screenHeight = 1080;

float cameraX = 0.f, cameraY = 0.f, cameraZ = 0.f;
float torLocX = 0.f, torLocY = 0.f, torLocZ = 0.f;
GLuint renderingProgram = 0, renderingProgramCubeMap = 0;

static const int numVAOs = 1;
static const int numVBOs = 5;
GLuint vao[numVAOs] = { 0 };
GLuint vbo[numVBOs] = { 0 };

GLuint brickTexture = 0, skyboxTexture = 0;
float rotAmt = 0.f;

// variable allocation for display
GLuint vLoc = 0, mvLoc = 0, projLoc = 0;
int width = 0, height = 0;
float aspect = 0.f;
glm::mat4 mMat(1.f), vMat(1.f), pMat(1.f), mvMat(1.f);


Torus myTorus(0.8f, 0.2f, 48);
int numTorusVertices = 0, numTorusIndices = 0;

Camera camera(glm::vec3(0.f, 0.f, 5.f));
GLboolean keys[1024] = { GL_FALSE };
GLboolean b_firstMouse = GL_TRUE;
float deltaTime = 0.f;

float lastFrame = 0.f;
float lastLocX = 0.f;
float lastLocY = 0.f;

void do_movement()
{
	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);
	}
	/*if (keys[GLFW_KEY_ESCAPE])
	{
		glfwSetWindowShouldClose(window, GL_TRUE);
	}*/
}

void key_press_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
	if ((key == GLFW_KEY_ESCAPE) && (action == GLFW_PRESS))
	{
		glfwSetWindowShouldClose(window, GL_TRUE);
	}
	if (action == GLFW_PRESS)
	{
		keys[key] = GLFW_TRUE;  //这里一定一定不能写成“==“,否则  按键WSAD按键失效!!!!!!!
	}
	else if (action == GLFW_RELEASE)
	{
		keys[key] = GLFW_FALSE;    //这里一定一定不能写成“==“,否则  按键WSAD按键失效!!!!!!!
	}
}

void mouse_move_callback(GLFWwindow* window, double xPos, double yPos)
{
	if (b_firstMouse)
	{
		lastLocX = xPos;
		lastLocY = yPos;
		b_firstMouse = GL_FALSE;
	}

	float xOffset = xPos - lastLocX;
	float yOffset = lastLocY - yPos;
	lastLocX = xPos;
	lastLocY = yPos;

	camera.ProcessMouseMovement(xOffset, yOffset);

}

void mouse_scroll_callback(GLFWwindow* window, double xPos, double yPos)
{
	camera.ProcessMouseScroll(yPos);
}


void setupVertices(void)
{
	float cubeVertexPositions[108] =
	{
		-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,  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, -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, -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,  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, -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,  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,  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,  1.0f, -1.0f,  1.0f, -1.0f
	};

	numTorusVertices = myTorus.getNumVertices();
	numTorusIndices = myTorus.getNumIndices();

	vector<int> ind = myTorus.getIndices();
	vector<glm::vec3> vert = myTorus.getVertices();
	vector<glm::vec2> text = myTorus.getTexCoords();
	vector<glm::vec3> norm = myTorus.getNormals();

	vector<float> pValues;
	vector<float> tValues;
	vector<float> nValues;

	for (int i=0; i<numTorusVertices; i++)
	{
		pValues.push_back(vert[i].x);
		pValues.push_back(vert[i].y);
		pValues.push_back(vert[i].z);

		tValues.push_back(text[i].s);
		tValues.push_back(text[i].t);

		nValues.push_back(norm[i].x);
		nValues.push_back(norm[i].y);
		nValues.push_back(norm[i].z);
	}

	glGenVertexArrays(numVAOs, vao);
	glBindVertexArray(vao[0]);

	glGenBuffers(numVBOs, vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertexPositions), cubeVertexPositions, GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
	glBufferData(GL_ARRAY_BUFFER, pValues.size() * sizeof(float), &pValues[0], GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
	glBufferData(GL_ARRAY_BUFFER, tValues.size() * sizeof(float), &tValues[0], GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[3]);
	glBufferData(GL_ARRAY_BUFFER, nValues.size() * sizeof(float), &nValues[0], GL_STATIC_DRAW);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[4]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, ind.size() * sizeof(int), &ind[0], GL_STATIC_DRAW);
}

void init(GLFWwindow* window)
{
	renderingProgram = Utils::createShaderProgram("vertShader.vert", "fragShader.frag");
	renderingProgramCubeMap = Utils::createShaderProgram("vertCubeShader.vert", "fragCubeShader.frag");

	glfwGetFramebufferSize(window, &width, &height);
	aspect = (float)width / (float)height;
	pMat = glm::perspective(toRadians(45.f), aspect, 0.01f, 1000.f);

	setupVertices();
	
	brickTexture = Utils::loadTexture("brick1.jpg");
	skyboxTexture = Utils::loadCubeMap("cubeMap");  // expects a folder name
	//开启GL_TEXTURE_CUBE_MAP_SEAMLESS在天空盒子的边缘将对两个交界面进行采样混合,否则边缘将采用单边像素,会出现明显的裂缝。
	glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);

	torLocX = 0.f, torLocY = 0.f, torLocZ = 0.f;
	cameraX = 0.f, cameraY = 0.f, cameraZ = 5.f;
}

void display(GLFWwindow* window, double currentTime)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClearColor(0.f, 0.5f, 1.f, 1.f);

	//vMat = glm::translate(glm::mat4(1.f), glm::vec3(cameraX, cameraY, cameraZ));

	// draw cube map
	glUseProgram(renderingProgramCubeMap);

	deltaTime = currentTime - lastFrame;
	lastFrame = currentTime;

	do_movement();
	//这句必须要有,否则鼠标中键失效
	pMat = glm::perspective(camera.Zoom, aspect, 0.01f, 1000.f);

	vMat = camera.GetViewMatrix();

	//没有这句,背景就没在相机视点上了,把圆环移到相机的位置
	mMat = glm::translate(glm::mat4(1.f), glm::vec3(cameraX, cameraY, 4.f));

	mvLoc = glGetUniformLocation(renderingProgramCubeMap, "mv_matrix");
	glUniformMatrix4fv(vLoc, 1, GL_FALSE, glm::value_ptr(mvMat));

	projLoc = glGetUniformLocation(renderingProgramCubeMap, "proj_matrix");
	glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));

	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxTexture);

	//开启剔除操作效果
	glEnable(GL_CULL_FACE);
	//GL_CCW 表示窗口坐标上投影多边形的顶点顺序为逆时针方向的表面为正面。
	//GL_CW    表示窗口坐标上投影多边形的顶点顺序为顺时针方向的表面为正面。
	glFrontFace(GL_CCW);
	glDisable(GL_DEPTH_TEST);
	glDrawArrays(GL_TRIANGLES, 0, 36);
	glEnable(GL_DEPTH_TEST);

	// draw scene (in this case it is just a torus)
	glUseProgram(renderingProgram);

	mvLoc = glGetUniformLocation(renderingProgram, "mv_matrix");
	projLoc = glGetUniformLocation(renderingProgram, "proj_matrix");

	mMat = glm::translate(glm::mat4(1.f), glm::vec3(torLocX, torLocY, torLocZ));
	mMat = glm::rotate(mMat, toRadians(35.f), glm::vec3(1.f, 0.f, 0.f));
	mvMat = vMat * mMat;


	glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvMat));
	glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));

	//vbo[0] 是立方体纹理贴图

	glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(1);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[3]);
	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(2);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[4]);
	glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(3);

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, brickTexture);

	glClear(GL_DEPTH_BUFFER_BIT);
	glEnable(GL_CULL_FACE);
	glFrontFace(GL_CCW);
	glDisable(GL_LEQUAL);
	glDrawArrays(GL_TRIANGLES, 0, 36);
	glEnable(GL_DEPTH_TEST);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[4]);
	glDrawElements(GL_TRIANGLES, numTorusIndices, GL_UNSIGNED_INT, 0);
}

void window_size_callback(GLFWwindow* window, int newWidth, int newHeight)
{
	aspect = (float)newWidth / (float)newHeight;
	glViewport(0, 0, newWidth, newHeight);
	pMat = glm::perspective(toRadians(45.f), aspect, 0.01f, 1000.f);
}

int main(int argc, char** argv)
{
	int glfwState = glfwInit();
	if (GLFW_FALSE == glfwState)
	{
		cout << "GLFW initialize failed,invoke glfwInit()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << endl;
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
	glfwWindowHint(GLFW_OPENGL_CORE_PROFILE, GLFW_OPENGL_PROFILE);

	GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "skybox opengl six face", nullptr, nullptr);
	if (!window)
	{
		cout << "GLFW create window failed,invoke glfwCreateWindow()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << endl;
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	glfwMakeContextCurrent(window);
	glfwSetWindowSizeCallback(window, window_size_callback);
	//glfwSetKeyCallback(window)

	int glewState = glewInit();
	if (GLEW_OK != glewState)
	{
		cout << "GLEW initialize failed,invoke glewInit()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << endl;
		glfwTerminate();
		exit(EXIT_FAILURE);
	}


	glfwSetWindowSizeCallback(window, window_size_callback);
	glfwSetCursorPosCallback(window, mouse_move_callback);
	glfwSetScrollCallback(window, mouse_scroll_callback);
	glfwSetKeyCallback(window, key_press_callback);

	init(window);

	while (!glfwWindowShouldClose(window))
	{
		display(window, glfwGetTime());
		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	glfwDestroyWindow(window);
	glfwTerminate();
	exit(EXIT_SUCCESS);


	return 0;
}

2.着色器程序

1.顶点着色器

#version 460 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
out vec2 tc;

uniform mat4 mv_matrix;
uniform mat4 proj_matrix;

layout(binding = 0) uniform sampler2D samp;

void main(void)
{
	tc = texCoord;
	gl_Position = proj_matrix * mv_matrix * vec4(position, 1.f);
}

2.片元着色器

#version 460 core

in vec2 tc;
out vec4 fragColor;

uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
layout(binding = 0) uniform sampler2D samp;

void main(void)
{
	fragColor = texture(samp, tc);
}

  1. 立方体顶点着色器
#version 460 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;

out vec3 tc;

uniform mat4 mv_matrix;
uniform mat4 proj_matrix;

layout(binding = 0) uniform sampler2D samp;

void main(void)
{
	tc = position;
	mat4 v3_matrix = mat4(mat3(mv_matrix));
	gl_Position = proj_matrix * v3_matrix * vec4(position, 1.f);
}

4.立方体片元着色器

#version 460 core

in vec3 tc;
out vec4 fragColor;

uniform mat4 mv_matrix;
uniform mat4 proj_matrix;

layout(binding = 0) uniform samplerCube samp;

void main(void)
{
	fragColor = texture(samp, tc);
}

运行结果

在这里插入图片描述

注意

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;

其中 location = 0,一定要和程序的顶点缓冲区vbo索引一致,否则渲染会出问题

如果写成这样:
在这里插入图片描述
运行结果
在这里插入图片描述
或者写成这样
在这里插入图片描述
中间圆环的纹理都会出问题

源码下载

源码下载地址

参考

计算机图形学编程 使用OpenGL和C++

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

使用OpenGL 立方体贴图 的相关文章

  • glColor4f() - alpha 值的效果

    我正在使用 glColor4f 令人惊讶的是 更改 alpha 即第四个参数 不会导致透明度发生任何变化 代码段是 const GLfloat squareVertices 0 5 0 5 0 0 0 5 0 5 0 0 0 5 0 5 0
  • 在 OpenGL 中使用不同的着色器程序?

    我必须在 OpenGL 中针对不同的对象使用两个不同的着色器程序 我发现我必须使用glUseProgram 在不同的着色器程序之间切换 但对此没有太多信息 鉴于我有两个用于不同对象的不同着色器程序 如何为每个着色器程序生成和绑定 VAO 和
  • GLSL 中统一浮点行为和常量浮点行为的不同

    我正在尝试在 GLSL 中实现模拟双精度 并且观察到一种奇怪的行为差异 导致 GLSL 中出现细微的浮点错误 考虑以下片段着色器 写入 4 浮点纹理以打印输出 layout location 0 out vec4 Output unifor
  • OpenGL:VAO 和 VBO 对于大型多边形渲染任务是否实用?

    如果您想渲染一次在视锥体中包含数千个多边形的大型景观 并且用户的视点不断变化 那么使用 VAO 或 VBO 是否实用 我的意思是 每次玩家的位置或摄像机旋转发生变化时 您都必须重新计算顶点数据 以便正确剔除不再可见的任何顶点或场景 以保持良
  • Windows下使用GLEW使用OpenGL扩展

    我一直在 Windows 上使用 OpenGL 扩展痛苦的方式 https stackoverflow com questions 14413 using opengl extensions on windows GLEW 是更简单的方法吗
  • OpenGL什么时候完成函数中指针的处理?

    OpenGL有多项功能 http www opengl org wiki GLAPI glTexSubImage2D直接获取指针 他们中有一些从这些指针读取数据 http www opengl org wiki GLAPI glBuffer
  • 渲染缓冲区大于窗口大小 - OpenGL

    我正在尝试绘制大于屏幕尺寸 即 320x480 的渲染缓冲区 512x512 执行 glReadPixels 后 图像看起来是正确的 除非图像的尺寸超过了屏幕尺寸 在本例中 超过了水平 320 和垂直 480 是什么原因导致这种异常现象呢
  • 创建并使用我自己的纹理图集的 mipmap

    我目前正在使用自动 mipmap 生成 C OpenTK GL GenerateMipmap GenerateMipmapTarget Texture2D 我使用的纹理平铺为 16px 的块 所以我的问题是 是否可以使用不会缩小至 1x1
  • 具有交错缓冲区的 openGL glDrawElements

    到目前为止 我只使用了 glDrawArrays 并希望转向使用索引缓冲区和索引三角形 我正在绘制一个有点复杂的对象 其中包含纹理坐标 法线和顶点坐标 所有这些数据都收集到一个交错的顶点缓冲区中 并使用类似于以下的调用进行绘制 假设所有血清
  • 无法在 QGLWidget 中设置所需的 OpenGL 版本

    我正在尝试在 Qt 4 8 2 中使用 QGLWidget 我注意到 QGLWidget 创建的默认上下文不显示 OpenGL 3 1 以上的任何输出 Qt wiki 有一个教程 http qt project org wiki How t
  • OpenSceneGraph 将相机设置在初始位置

    我是第一次使用 OpenSceneGraph 我有点迷失 因为文档确实不太清楚 所以 我有这段代码加载一个带有房子的 obj 文件 并且我在我想要的 人 所在的地方淹没了一个小盒子 所以现在 我不想把那个盒子放在那里 而是想把相机放在那里
  • 使用普通画布/文本输出更新LayeredWindow

    有没有一种方法可以使用画布在表单上绘图 然后使用 updatelayeredwindow 这样表单就不可见 但文本可见 就像只显示文本的半透明表单一样 如果没有 那么有没有办法只用画布 opengl directx 制作某种半透明形式 我想
  • 使用顶点缓冲区对象 (VBO) 渲染 Kinect 点云

    我正在尝试制作一个动态点云可视化工具 使用 Kinect 传感器每帧更新这些点 为了抓取帧 我使用 OpenCV 和 GLUT 来显示 OpenCV API 对于点 xyz 位置返回 640 x 480 float 对于 rgb 颜色数据返
  • 为贝塞尔曲线中的每个点绘制切线

    我设法绘制了一条贝塞尔曲线 如下所示 glColor3f 0 1 0 glBegin GL LINE STRIP for int i 3 i lt nPt i 3 glColor3f 0 0 0 for float k 0 k lt NLI
  • 使用 OpenGL 渲染 QImage

    与我相关的其他问题 https stackoverflow com questions 20126354 render qimage from sooffscreenrenderer in qglwidget 我认为更核心的问题是 如何渲染
  • 新显卡上的 nvoglv32.dll 中的绘制调用崩溃

    几天前 由于一些硬件更改 我设置了计算机并安装了新的 Windows 8 副本 其中 我将显卡从 Radeon HD 7870 更改为 Nvidia GTX 660 再次设置 Visual Studio 11 后 我从 Github 下载了
  • GLSL memoryBarrierShared() 有用吗?

    我想知道 memoryBarrierShared 的用处 事实上 当我查找屏障功能的文档时 我读到 对于计算着色器中任何给定的静态屏障实例 单个工作组内的所有调用都必须进入该实例 然后才能允许任何调用继续超出该实例 这确保了在给定的屏障静态
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲
  • 光照不适用于 gluSphere

    这是一个简单的问题 我有点羞于寻求帮助 我正在对 gluSphere 进行简单调用来渲染球体 但是 即使我很确定我正确添加了法线和照明 它也无法正确照亮 但是 如果我添加纹理 模型会正常点亮 但它似乎总是平滑的 并且我无法将其更改为平面 这
  • 如何在 Moderngl EGL 后端添加深度缓冲区?

    此代码渲染一个带有抗锯齿功能的彩色三角形 samples 8 当深度缓冲线depth attachment ctx depth texture 512 512 samples 8 被评论 但是当我添加深度缓冲区时 它会在绑定处返回 GL 错

随机推荐

  • linux 线程局部存储,tls_windows

    线程局部存储 线程局部存储 thread local storage TLS 是一个使用很方便的存储线程局部数据的系统 利用TLS机制可以为进程中所有的线程关联若干个数据 各个线程通过由TLS分配的全局索引来访问与自己关联的数据 这样 每个
  • v-model绑定checkbox无法动态更新视图

    在vue2中使用v model绑定checkbox
  • Python爬虫(入门+进阶)学习笔记 1-6 浏览器抓包及headers设置(案例一:爬取知乎)

    爬虫的一般思路 抓取网页 分析请求 解析网页 寻找数据 储存数据 多页处理 本节课主要讲授如何通过谷歌浏览器开发者工具分析真实请求的方法 寻找真实请求的三个步骤 分析 使用谷歌浏览器开发者工具分析网页的请求 测试 测试URL请求中每个参数的
  • echarts实现颜色渐变的环状图(包括自定义各种配置项的属性)

    实现效果 实现代码 option color new echarts graphic LinearGradient 1 1 0 0 offset 0 color F2A635 offset 0 9 color ffffff new echa
  • 为Qt应用程序的用户添加帮助文档

    qt5 简单文本查看器例子 Qt Assistant支持交互式帮助 并使您能够向Qt应用程序的用户显示客户文档 以下示例说明如何将Qt Assistant用作应用程序的帮助查看器 使用Qt Assistant作为应用程序的自定义help查看
  • Oracle V$SESSION详解

    V SESSION是APPS用户下面对于SYS V SESSION 视图的同义词 在本视图中 每一个连接到数据库实例中的session都拥有一条记录 包括用户session及后台进程如DBWR LGWR arcchiver等等 V SESS
  • 大数据环境下的“隐形隐私”保护问题

    导语 隐形隐私 泄漏问题一直我们乃至全球最难解决的问题 数据安全不止是一个企业发展的核心关键 更关系到企业单位的生死存亡 企业单位重要客户信息泄露并在市面上大肆流通发生之后我们在想尽各种方法亡羊补牢 可是我们数据安全难道不是要从最一开始就做
  • 针对初学者,解决一些问题【Kali】手把手教你设置Kali源地址以及更新源和安装所有工具命令

    文章目录 一 设置添加修改源地址 1 首先在命令提示符中输入以下命令打开源列表文件 2 按i进入编辑模式 3 在下面源地址中至少选择一个复制粘贴进去 4 添加进入以后按ESC键退出编辑模式 按 输入wq保存退出 二 更新源命令 三 软件包操
  • TCP为什么需要三次握手

    tcp为什么要第三次握手 time wait是做什么的 tcp有几种状态 画出所有的状态转换图 晚上看到的面试题 TCP三次握手的印象很深 但为什么需要3次握手 还是想不起来了 简单而言 如果不是三次握手的话 那么到底需要几次握手最佳呢 2
  • 关于毕业求职的就业经验-写给我亲爱的校友们

    提示 希望下面的文章对大家能有所帮助 文章目录 前言 一 毕业季的几种选择 1 考研 2 就业 3 其他 二 到了毕业季应该怎么去找到自己心怡的工作 三 需要掌握的基本技能 以我嵌入式开发角度 四 该怎么去跳槽到更好的公司 五 未来规划 1
  • SPARK安装

    首先是结论 最终我没能在win10上运行起来spark 官方给的quickstart http spark apache org docs latest api python getting started quickstart html
  • Matlab学习1.0

    1 Matlab通用命令 1 常用命令 cd 显示 or改变当前文件夹 dir 显示当前文件夹下的文件 clc 清空工作窗中显示的内容 load 加载指定文件的变量 diary 日志文件命令 调用DOS命令 home 光标移动到窗口最左上角
  • 网络安全知识库

    0x00 前言 本篇用来整理所有的零散的知识 作为一个技能树或者技能表来进行引导 CTF 加解密合集 CTF Web合集 0x01 Http 1 http头 1 1 本地访问识别 如何伪造http头 让后端认为是本地访问 0x02 Web
  • Python爬虫反反爬:CSS反爬加密彻底破解!

    刚开始搞爬虫的时候听到有人说爬虫是一场攻坚战 听的时候也没感觉到特别 但是经过了一段时间的练习之后 深以为然 每个网站不一样 每次爬取都是重新开始 所以 爬之前谁都不敢说会有什么结果 前两天 应几个小朋友的邀请 动心思玩了一下大众点评的数据
  • css动画效果之transition(动画过渡效果属性)

  • pandas dataframe 读取 xlsx 文件

    refer to https medium com kasiarachuta reading and writingexcel files in python pandas 8f0da449cc48 dframe pd read excel
  • github代码推送总是失败

    github代码推送问题 因为github仓库代码的推送总是失败 所以改了一个方案采用ssh的方式来进行代码的推送 并记录操作步骤 方案 https方式换成ssh方式 git ssh 生成 假如已经生成的话 可以略过此步骤 ssh keyg
  • Android启动service的方法

    在 Android 中启动 service 的方法如下 创建 service 的类 并在 AndroidManifest xml 文件中注册该 service 使用 Intent 类来启动 service 例如 Intent intent
  • [转]公司管理混乱,从哪里入手?

    案例分析 我们是一个40人左右的小公司 规模虽小 但管理起来感觉力不从心 经常碰到工人抵抗 情绪化 上班迟到 旷工 不服从管理 即使勉强接受 也不会用心去做 草草应付了事 每次都提议是否弄个规章制度 但也是白纸一张 到了月底 实施不了 因为
  • 使用OpenGL 立方体贴图

    openGL系列文章目录 文章目录 openGL系列文章目录 前言 一 OpenGL 立方体贴图 二 使用步骤 1 代码 2 着色器程序 运行结果 注意 源码下载 参考 前言 对于室外3D 场景 通常可以通过在地平线上创造一些逼真的效果 来