openGL使用高度贴图模拟地球表面凹凸效果

2023-11-02

openGL系列文章目录

前言

不少模型都会附带以“bump”为名结尾的贴图,这种帖图统称为凹凸贴图,目的是为了体现出物体的凹凸不平,最经典的例子就是法线贴图,有兴趣的朋友可以看看。除此之外还有高度贴图、浮雕贴图等,不过这里暂时先只了解高度帖图吧
高度贴图又称视差贴图,用于直接给予纹理显示上的错觉,视差贴图往往都是黑白图,因为理论上只需要知道每个纹理的深度值,因此RGB三个值都是相等的,就如下:
如果对应的像素是黑色的,意味着此纹理的高度为0,也就是默认值,如果一张高度图为全黑那就相当于没有高度图一样,像素点越接近白色,就代表着当前像素点越“凹”,之前渲染的地板看上去有点花,就如下:
在这里插入图片描述

在这里插入图片描述

一、高度贴图是什么

现在我们扩展法线贴图的概念——从纹理图像用于扰动法向量到扰乱顶点位置本身。实
际上,以这种方式修改对象的几何体具有一定的优势,例如使表面特征沿着对象的边缘可
见,并使特征能够响应阴影贴图。我们将会看到,它还可以帮助构建地形。
一种实用的方法是使用纹理图像来存储高度值,然后使用该高度值来提升(或降低)顶
点位置。含有高度信息的图像称为高度图,使用高度图更改对象的顶点的方法称为高度贴
图①。高度图通常将高度信息编码为灰度颜色:(0,0,0)(黑色)=低高度,(1,1,1)(白色)=
高高度。这样一来通过算法或使用“画图”程序就可以轻松创建高度图。图像的对比度越
高,其表示的高度变化越大。这些概念将在图10.12(显示随机生成的地图)和图10.13(显
示有组织的模式的地图)中说明。

二、代码

1.c++主程序

#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 "Sphere.h"
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

static const int screenWidth = 1920;
static const int screenHeight = 1080;
int width = 0, height = 0;

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

static const int numVAOs = 1;
static const int numVBOs = 4;

float cameraX = 0.f, cameraY = 0.f, cameraZ = 0.f;
float sphereX = 0.f, sphereY = 0.f, sphereZ = 0.f;
float lightLocX = 0.f, lightLocY = 0.f, lightLocZ = 0.f;

GLuint renderingProgram = 0;
GLuint vao[numVAOs] = { 0 };
GLuint vbo[numVBOs] = { 0 };

// variable allocation for display
GLuint mvLoc = 0, projLoc = 0, nLoc = 0;
GLuint globalAmbLoc = 0, ambLoc = 0, diffLoc = 0, specLoc = 0, posLoc = 0, mAmbLoc = 0, mDiffLoc = 0, mSpecLoc = 0, mShinLoc = 0;
float aspect = 0;
glm::mat4 mMat(1.f), vMat(1.f), pMat(1.f), mvMat(1.f), invTrMat(1.f);
glm::vec3 currentLightPos(0.f);
float lightPos[3] = { 0.f };
float rotAmb = 0.f;

Sphere mySphere(96);
int numSphereVertices = 0;
int numSphereIndices = 0;

GLuint colorTexture = 0;
GLuint normalTexture = 0;
GLuint heightTexture = 0;

// white light
float globalAmbient[4] = { 0.1f, 0.1f, 0.1f, 1.f };
float lightAmbient[4] = { 0.f, 0.f, 0.f, 1.f };
float lightDiffuse[4] = { 1.0f, 1.0f, 1.f, 1.f };
float lightSpecular[4] = { 1.f, 1.f, 1.f, 1.f };

// silver material
float* matAmbi = Utils::silverAmbient();
float* matDiff = Utils::silverDiffuse();
float* matSpec = Utils::silverSpecular();
float  matShin = Utils::silverShininess();

Camera camera(glm::vec3(0.f, 0.f, 1.f));
//float cameraX = 0.f, cameraY = 0.f, cameraZ = 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()
{
	int numSphereVertices = mySphere.getNumVertices();
	numSphereIndices = mySphere.getNumIndices();
	vector<int> ind = mySphere.getIndices();
	vector<glm::vec3> vert = mySphere.getVertices();
	vector<glm::vec2> text = mySphere.getTexCoords();
	vector<glm::vec3> norm = mySphere.getNormals();
	vector<glm::vec3> tang = mySphere.getTangents();

	vector<float> pValuse;
	vector<float> tValues;
	vector<float> nValues;
	vector<float> tanValues;


	for (int i = 0; i< mySphere.getNumIndices(); i++)
	{
		//pValuse.push_back(vert[ind[i]].x);
		pValuse.push_back(vert[ind[i]].x);
		pValuse.push_back(vert[ind[i]].y);
		pValuse.push_back(vert[ind[i]].z);

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

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

		tanValues.push_back(tang[ind[i]].x);
		tanValues.push_back(tang[ind[i]].y);
		tanValues.push_back(tang[ind[i]].z);
	}

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

	glGenBuffers(numVBOs, vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBufferData(GL_ARRAY_BUFFER, pValuse.size() * sizeof(float), &pValuse[0], GL_STATIC_DRAW);

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

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

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

void installLights(glm::mat4 vMatrix)
{
	glm::vec3 transformed = glm::vec3(vMatrix * glm::vec4(currentLightPos, 1.f));
	lightPos[0] = transformed.x;
	lightPos[1] = transformed.y;
	lightPos[2] = transformed.z;

	// get the locations of the light and material fields in the shader
	globalAmbLoc = glGetUniformLocation(renderingProgram, "globalAmbient");
	ambLoc = glGetUniformLocation(renderingProgram, "light.ambient");
	diffLoc = glGetUniformLocation(renderingProgram, "light.diffuse");
	specLoc = glGetUniformLocation(renderingProgram, "light.specular");
	posLoc = glGetUniformLocation(renderingProgram, "light.position");
	mAmbLoc = glGetUniformLocation(renderingProgram, "material.ambient");
	mDiffLoc = glGetUniformLocation(renderingProgram, "material.diffuse");
	mSpecLoc = glGetUniformLocation(renderingProgram, "material.specular");
	mShinLoc = glGetUniformLocation(renderingProgram, "material.shininess");

	//  set the uniform light and material values in the shader
	glUniformMatrix4fv(globalAmbLoc, 1, GL_FALSE, globalAmbient);
	glUniformMatrix4fv(ambLoc, 1, GL_FALSE, lightAmbient);
	glUniformMatrix4fv(diffLoc, 1, GL_FALSE, lightDiffuse);
	glUniformMatrix4fv(specLoc, 1, GL_FALSE, lightSpecular);
	glUniformMatrix3fv(posLoc, 1, GL_FALSE, lightPos);
	glUniformMatrix4fv(mAmbLoc, 1, GL_FALSE, matAmbi);
	glUniformMatrix4fv(mDiffLoc, 1, GL_FALSE, matDiff);
	glUniformMatrix4fv(mSpecLoc, 1, GL_FALSE, matSpec);
	glUniform1f(mShinLoc, matShin);

	/*glProgramUniform4fv(renderingProgram, globalAmbLoc, 1, globalAmbient);
	glProgramUniform4fv(renderingProgram, ambLoc, 1, lightAmbient);
	glProgramUniform4fv(renderingProgram, diffLoc, 1, lightDiffuse);
	glProgramUniform4fv(renderingProgram, specLoc, 1, lightSpecular);
	glProgramUniform3fv(renderingProgram, posLoc, 1, lightPos);
	glProgramUniform4fv(renderingProgram, mAmbLoc, 1, matAmbi);
	glProgramUniform4fv(renderingProgram, mDiffLoc, 1, matDiff);
	glProgramUniform4fv(renderingProgram, mSpecLoc, 1, matSpec);
	glProgramUniform1f(renderingProgram, mShinLoc, matShin);*/
}

void init(GLFWwindow* window)
{
	renderingProgram = Utils::createShaderProgram("vertShader.vert", "fragShader.frag");
	cameraX = 0.f, cameraY = 0.f, cameraZ = 2.f;
	sphereX = 0.f, sphereY = 0.f, sphereZ = -1.f;
	lightLocX = 3.f, lightLocY = 2.f, lightLocZ = 3.f;   //试着改变光源位置,看变化效果
	
	glfwGetFramebufferSize(window, &width, &height);
	aspect = (float)width / (float)height;
	pMat = glm::perspective(toRadians(45.f), aspect, 0.01f, 1000.f);

	setupVertices();

	colorTexture = Utils::loadTexture("earthspec1kBLUE.jpg");
	normalTexture = Utils::loadTexture("earthspec1kNORMAL.jpg");
	heightTexture = Utils::loadTexture("earthspec1kNEG.jpg");
}

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

	glUseProgram(renderingProgram);

	deltaTime = currentTime - lastFrame;
	lastFrame = currentTime;

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

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

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

	glfwGetFramebufferSize(window, &width, &height);
	aspect = (float)width / (float)height;
	pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);

	//vMat = glm::translate(glm::mat4(1.f), glm::vec3(-cameraX, -cameraY, -cameraZ));
	mMat = glm::translate(glm::mat4(1.f), glm::vec3(sphereX, sphereY, sphereZ));
	mMat = glm::rotate(mMat, toRadians(35.f), glm::vec3(0.f, 1.f, 0.f));
	mMat = glm::rotate(mMat, rotAmb, glm::vec3(0.f, 1.f, 0.f));
	rotAmb += 0.002f;
	mvMat = vMat * mMat;
	invTrMat = glm::transpose(glm::inverse(mvMat));

	currentLightPos = glm::vec3(lightLocX, lightLocY, lightLocZ);
	installLights(mvMat);  //vMat

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

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

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

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

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

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

	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, normalTexture);

	glActiveTexture(GL_TEXTURE2);
	glBindTexture(GL_TEXTURE_2D, heightTexture);

	glEnable(GL_CULL_FACE);
	glFrontFace(GL_CCW);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

	glDrawArrays(GL_TRIANGLES, 0, mySphere.getNumIndices());
}

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);
	glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);

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

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

	glfwSwapInterval(1);

	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 vertPos;
layout(location = 1) in vec2 texCoord;
layout(location = 2) in vec3 vertNormal;
layout(location = 3) in vec3 vertTangent;

out vec3 varyingLightDir;
out vec3 varyingVertPos;
out vec3 varyingNormal;
out vec3 varyingTangent;
out vec2 tc;

layout(binding = 0) uniform sampler2D t;
layout(binding = 1) uniform sampler2D n;
layout(binding = 2) uniform sampler2D h;

struct PositionalLight
{
	vec4 ambient;
	vec4 diffuse;
	vec4 specular;
	vec3 position;
};

struct Material
{
	vec4 ambient;
	vec4 diffuse;
	vec4 specular;
	float shininess;
};

uniform vec4 globalAmbient;
uniform PositionalLight light;
uniform Material material;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
uniform mat4 norm_matrix;

void main(void)
{
	varyingNormal = (norm_matrix * vec4(vertNormal, 1.f)).xyz;
	varyingTangent = (norm_matrix * vec4(vertTangent, 1.f)).xyz;

	vec4 P1 = vec4(vertPos, 1.f);
	vec4 P2 = vec4((vertNormal * ((texture(h, texCoord).r) / 15.f)), 1.f);
	vec4 P = vec4((P1.xyz + P2.xyz), 1.f);

	varyingVertPos = (mv_matrix * P).xyz;
	varyingLightDir = light.position - varyingVertPos;

	tc = texCoord;
	gl_Position = proj_matrix * mv_matrix * P;  //MVP
}

2.片元着色器

#version 460 core

in vec3 varyingLightDir;
in vec3 varyingVertPos;
in vec3 varyingNormal;
in vec3 varyingTangent;
in vec2 tc;

out vec4 fragColor;

layout(binding = 0) uniform sampler2D t;
layout(binding = 1) uniform sampler2D n;
layout(binding = 2) uniform sampler2D h;

struct PositionalLight
{
	vec4 ambient;
	vec4 diffuse;
	vec4 specular;
	vec3 position;
};

struct Material
{
	vec4 ambient;
	vec4 diffuse;
	vec4 specular;
	float shininess;
};

uniform vec4 globalAmbient;
uniform PositionalLight light;
uniform Material material;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
uniform mat4 norm_matrix;

vec3 CalcBumpedNormal()
{
	vec3 Normal = normalize(varyingNormal);
	vec3 Tangent = normalize(varyingTangent);
	Tangent = normalize(Tangent - dot(Tangent, Normal) * Normal);
	vec3 bitangent = cross(Tangent, Normal);
	vec3 bumpMapNormal = texture(n, tc).xyz;
	bumpMapNormal = bumpMapNormal * 2.f - 1.f;
	mat3 TBN = mat3(Tangent, bitangent, Normal);
	vec3 newNormal = TBN * bumpMapNormal;
	newNormal = normalize(newNormal);

	return newNormal;
}

void main(void)
{
	// normalize the light, normal, and view vectors:
	vec3 L = normalize(varyingLightDir);
	vec3 V = normalize(varyingVertPos);

	//vec3 N = CalcBumpedNormal();
//	vec3 N = normalize(varyingNormal);
//vec3 N = CalcBumpedNormal();
	vec3 N = CalcBumpedNormal();

	// get the angle between the light and surface normal:
	float cosTheta = dot(L, N);

	// compute light reflection vector, with respect N:
	vec3 R = normalize(reflect(-L, N));

	// angle between the view vector and reflected light:
	float cosPhi = dot(V, R);

	// compute ADS contributions (per pixel):
	fragColor = 0.5f * texture(t, tc) + 0.5f * (fragColor = globalAmbient * material.ambient
			    + light.ambient * material.ambient
				+ light.diffuse * material.diffuse * max(cosTheta, 0.0f)
				+ light.specular * material.specular * pow(max(cosPhi, 0.f), material.shininess));


}

 

运行效果

在这里插入图片描述

源码下载

源码下载地址

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

openGL使用高度贴图模拟地球表面凹凸效果 的相关文章

  • OpenGL,如何独立旋转对象?

    到目前为止我的代码 void display void glClear GL COLOR BUFFER BIT GL DEPTH BUFFER BIT Clear Screen And Depth Buffer glLoadIdentity
  • glVertexAttribDivisor 和 glVertexBindingDivisor 有什么区别?

    我一直在寻找将属性与任意顶点分组关联起来的方法 起初似乎是我实现这一目标的唯一方法 但后来我偶然发现了这个问题 https stackoverflow com questions 14169228 opengl single vertex
  • 帧缓冲区/颜色缓冲区?

    有人可以指出我两者是否相同吗 我的意思是我一直在阅读有关它的信息 这里的红皮书说 颜色缓冲区本身可以由多个子缓冲区组成 系统上的帧缓冲区包含所有这些缓冲区 here http glprogramming com red chapter10
  • GLSL 中统一浮点行为和常量浮点行为的不同

    我正在尝试在 GLSL 中实现模拟双精度 并且观察到一种奇怪的行为差异 导致 GLSL 中出现细微的浮点错误 考虑以下片段着色器 写入 4 浮点纹理以打印输出 layout location 0 out vec4 Output unifor
  • 渲染 TTF SDL2.0 opengl 3.1

    我正在使用 SDL2 0 并使用 半现代 opengl 3 1 我希望向我的应用程序添加文本叠加 并在应用程序中呈现 TTF 我将如何使用现代 OpenGL 来解决这个问题 编辑 根据 genpfault 的建议 我尝试使用 SDL TTF
  • 如何计算正切和副法线?

    谈谈OpenGL着色语言 GLSL 中的凹凸贴图 镜面高光之类的东西 I have 顶点数组 例如 0 2 0 5 0 1 0 2 0 4 0 5 法线数组 例如 0 0 0 0 1 0 0 0 1 0 0 0 世界空间中点光源的位置 例如
  • GL_COLOR_ATTACHMENT 有什么作用?

    我现在正在学习帧缓冲区 但我只是不明白颜色附件的作用 我了解帧缓冲区 第二个参数的意义是什么 glFramebufferTexture2D GL FRAMEBUFFER GL COLOR ATTACHMENT0 GL TEXTURE 2D
  • 在 OpenGL 中渲染纹理 1 到 1

    所以我想做的是使用 OpenGL 和 C 将纹理渲染到平面上 作为显示图像的一种方式 但是我需要确保在渲染纹理时没有对纹理进行任何处理 抗锯齿 插值 平滑 模糊等 这是 OpenGL 处理渲染纹理的默认方式吗 或者是否需要设置一些标志才能禁
  • OpenGL:始终相同的颜色

    我正在 Windows 上编写一个程序 使用c opengl 2 1 and SDL我在顶点颜色方面遇到了一些问题 我在用着glColor3f设置每个顶点集的颜色 但它似乎不起作用 无论我选择什么颜色 我都会将每个顶点绘制为红色 我检查了传
  • 渲染缓冲区大于窗口大小 - OpenGL

    我正在尝试绘制大于屏幕尺寸 即 320x480 的渲染缓冲区 512x512 执行 glReadPixels 后 图像看起来是正确的 除非图像的尺寸超过了屏幕尺寸 在本例中 超过了水平 320 和垂直 480 是什么原因导致这种异常现象呢
  • 在 OpenGL 中实例化数百万个对象:提高每秒帧数

    我的最终目标是以 60 fps 渲染 100 万个不同尺寸和颜色的球体 我也希望能够在屏幕上移动相机 我已经修改了代码我正在学习的教程的这一页 http learnopengl com Advanced OpenGL Instancing尝
  • 如何为 glDrawElements() 指定每个图元的颜色

    我想渲染一个索引几何体 所以 我有一堆顶点和关联的排序索引 我在用glDrawElements 渲染 2 个四边形 如下所示 现在 我知道我可以使用glColorPointer 用于指定每个顶点的颜色 我的问题是 我可以指定吗每个基元的颜色
  • 渲染到一个颜色通道而不影响其他通道

    使用 OpenGL 任何版本 如何通过一次仅影响一个颜色通道来渲染到帧缓冲区对象 例如 我的帧缓冲区对象具有 GL BGRA 布局 现在我想执行一些渲染命令 这些命令应该只改变红色通道 因此 如果片段用颜色 204 0 0 0 渲染并且像素
  • 无法在 QGLWidget 中设置所需的 OpenGL 版本

    我正在尝试在 Qt 4 8 2 中使用 QGLWidget 我注意到 QGLWidget 创建的默认上下文不显示 OpenGL 3 1 以上的任何输出 Qt wiki 有一个教程 http qt project org wiki How t
  • 使用 gl_FragColor 与 vec4 颜色?

    似乎有很多不明确的地方gl FragColor被弃用 例如 它缺失在GLSL 4 40 规范 https www khronos org registry OpenGL specs gl GLSLangSpec 4 40 pdf 但它包含在
  • 仅在发布模式下使用 glGenBuffer 时出现未处理的异常 - QT

    我在 Windows 7 上使用 Qt 4 8 发布模式编译项目时遇到了一些问题 调试时一切正常 但在发布时我收到未处理的异常 0xC0000005 访问冲突 我将范围缩小到发生这种情况的行 即生成像素缓冲区的时间 我的第一个猜测是 DLL
  • glTranslatef 不在 glBegin .. glEnd 中工作

    我正在尝试并排绘制不同颜色的两个方块 我的问题是我无法让 glTranslatef 将第二个方块向右移动 第二个方块只是绘制在第一个方块上 void display void glClear GL COLOR BUFFER BIT glMa
  • GLSL memoryBarrierShared() 有用吗?

    我想知道 memoryBarrierShared 的用处 事实上 当我查找屏障功能的文档时 我读到 对于计算着色器中任何给定的静态屏障实例 单个工作组内的所有调用都必须进入该实例 然后才能允许任何调用继续超出该实例 这确保了在给定的屏障静态
  • OpenGL/GLSL - 纹理过滤的实现

    我想在 GLSL 着色器中自己实现纹理过滤 min 和 magfilter 因为我想使用 image load and store 而不是采样器 而且我想以特殊方式处理未定义的像素 并且我正在寻找一篇文章或者这样讨论过滤过程 我记得如何从我
  • 3D 图形批处理

    很多网站 文章都说 批量 批 批 有人可以解释一下着色器中的 批处理 代表什么吗 即 是否 改变纹理 更改任意着色器变量 意味着某些东西不能 批处理 最简单的总结方法就是尝试尽可能少地调用 API 来绘制您需要绘制的内容 使用顶点数组或 V

随机推荐

  • Redis持久化存储RDB(写时复制)/AOF

    快照 RDB save 会阻塞当前Redis服务器 直到持久化完成 线上应该禁止使用 明确时间点 关机维护 bgsave fork一个子进程 由子进程负责持久化过程 父进程发生写操作修改内存数据时 Copy On Write 才会真正去分配
  • NFS服务详解

    文章目录 一 NFS概述 二 NFS工作原理 2 1NFS工作流程 2 2挂载原理 三 NFS服务部署 3 1常用命令 3 2服务器端配置 3 3客户端配置 3 4服务测试 四 总结 一 NFS概述 1 概述 NFS是一种基于TCP IP
  • 分享菜鸟学Python,从入门到进阶的心得

    来自一位投稿粉丝的学习心得 从最初学Python从爬虫开始 到数据分析 再到GUI的实现 以及后来的机器学习和深度学习文章 我与大家已经走过了好几个月的时间 在这几个月的时间里 我通过文章与大家一同学习 一同进步 向大家展示了如何通过Pyt
  • 第三章 分类模型-随机森林知识点详细总结

    机器学习算法系列 第一章 Python Spark 分类模型 逻辑回归知识点详细总结 第二章 分类模型 决策树知识点详细总结 第三章 分类模型 随机森林知识点详细总结 第四章 分类模型 支持向量机SVM知识点详细总结第五章 关联分析 apr
  • CocosCreator3.8研究笔记(十四)CocosCreator 资源管理Asset Manager

    在游戏的开发过程中 需要使用到大量的图片 音频等资源来 从而带来管理上的困难 Asset Manager 资源管理模块具备加载资源 查找资源 销毁资源 缓存资源 Asset Bundle 等功能 帮助开发者管理其资源的使用 一 资源的加载
  • IHO ENC

    IHO ENC Electronic Navigation Chart is specially specified for marine navigation and defined by IHO International Hydrol
  • CMD批处理实现dot命令自动运行更新

    CMD批处理实现dot命令自动运行更新 前言 一 编写bat脚本 二 解释 总结 前言 最近学习dot语言 我们知道 运行dott脚本大致有两种方法 使用Gvedit编辑dot代码并直接点击运行按钮运行 使用记事本编辑工具编辑号dott脚本
  • 通过adb命令卸载小米手机预设的应用

    文章目录 准备环境 具体步骤 附 准备环境 首先介绍adb命令 ADB是Android Debug brige 是一种用于于安卓设备通信的命令行工具 卸载应用需要用到这个命令 adb命令安装方法 1 adb工具下载 下载适合您的系统的 AD
  • 什么是 I18N 和 L10N ?

    什么是 I18N 和 L10N I18N 是 internationalization 的缩写形式 意即在 i 和 n 之间有 18 个字母 本意是指软件的 国际化 与之类似 L10N 是 localization 的缩写形式 意即在 l
  • 用python写一个hello world、把代码写下来_编程与下厨房:如何教女友写Python(二:不从Hello World开始...

    一 不从 Hello World 开始 但凡是介绍编程语言的入门书籍 都会把 hello world 这个句子的输出作为第一个程序的示例 这种约定俗成的做法就像是新居进火的仪式一般具有非凡的意义 但是在这里 我们并不打算将Python的第一
  • Windows中d3dcompiler_33.dll丢失怎么解决

    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题 如果是新手第一时间会认为是软件或游戏出错了 其实并不是这样 其主要原因就是你电脑系统的该dll文件丢失了或者损坏了 这时你只需下载这个d3dcompiler 33 dll文件进行安装
  • Merkle Tree与区块链

    什么是merkle tree 假设你已经知道了什么是哈希算法以及哈希是用来干啥的 网络传输数据的时候 A收到B的传过来的文件 需要确认收到的文件有没有损坏 如何解决 有一种方法是B在传文件之前先把文件的hash结果给A A收到文件再计算一次
  • 从零开始的ESP8266探索(17)-Client(客户端)功能使用

    文章目录 目的 使用说明 作为TCP Client使用 作为WEB Client使用 总结 目的 前面的文章中有介绍使用Server 服务器 功能 这里的Server和Client指的是基本的TCP的Server和Client 当然就像前面
  • 关于List泛型的强制转换(java list强制类型转换)

    转载只为收藏好文 原文地址 https www cnblogs com hihtml5 p 6194460 html 当我们从数据库中查询出一些数据 有时返回的结果可能是List类型 而我们清楚的知道它的准确类型是List
  • 常用的加密算法

    一 对称加密 所谓的对称加密就是加密跟解密使用同一把密钥 常见的对称加密算法有AES DES等等 下面以DES加密算法为例 Java语言实现DES加密 Java语言实现DES解密 对于不同的对称加密算法 密钥的位数是不同的 对于DES加密算
  • Thymeleaf模板引擎

    1 thymeleaf简介 1 1 什么是thymeleaf Thymeleaf是适用于Web和独立环境的现代服务器端Java模板引擎 能够处理HTML XML JavaScript CSS甚至纯文本 Thymeleaf的主要目标是提供一种
  • LeetCode05 最长回文子串 java(动态规划)

    题目 给定一个字符串 s 找到 s 中最长的回文子串 你可以假设 s 的最大长度为 1000 示例 1 输入 babad 输出 bab 注意 aba 也是一个有效答案 示例 2 输入 cbbd 输出 bb 分析 初始状态 dp i i 1
  • flex 中文API

    http help adobe com zh CN AS3LCR Flex 4 0
  • 微软服务器漏洞,微软SMBv3客户端/服务端远程代码执行漏洞(CVE-2020-0796)技术分析...

    微软安全中心在北京时间3月12日23时发布了影响Windows 10 等系统用户的SMBv3远程代码执行漏洞补丁 我们建议受影响的用户尽快按微软更新信息指南安装该补丁 https portal msrc microsoft com en U
  • openGL使用高度贴图模拟地球表面凹凸效果

    openGL系列文章目录 文章目录 openGL系列文章目录 前言 一 高度贴图是什么 二 代码 1 c 主程序 2 着色器程序 运行效果 源码下载 前言 不少模型都会附带以 bump 为名结尾的贴图 这种帖图统称为凹凸贴图 目的是为了体现