glEnable(GL_CULL_FACE | GL_DEPTH_TEST);出现纹理重叠现象

openGL系列文章目录

前言

今天遇到一个奇怪的问题,绘制圆环体。在给圆环体问题贴图的时候感觉总有问题,纹理有重叠。

  1. 如果代码是:
glEnable(GL_CULL_FACE | GL_DEPTH_TEST); 

产生的效果是:
在这里插入图片描述
2. 如果代码是:
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
产生的效果是:
在这里插入图片描述
可以看到两张图片的明显差别
在这里插入图片描述

一、问题

可以看到左边的圆环纹理有扭曲

二、问题解决

 glEnable(GL_CULL_FACE | GL_DEPTH_TEST); 

改成

glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);

主要代码

#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 "Utils.h"
#include "Torus.h"
#include "SOIL2/SOIL2.h"
#include "camera.h"
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

static const float pai = 3.1415926f;


float toRadins(float degress)
{
	return (degress * 2.f * 3.14159f / 360.f);
}

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

float cameraX = 0.f, cameraY = 0.f, cameraZ = 0.f;
float torusLocX = 0.f, torusLocY = 0.f, torusLocZ = 0.f;

GLuint renderingProgram = 0;

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

static const int screen_width = 1920;
static const int screen_height = 1080;



GLuint torusTextureId = 0;
float rotAmt = 0.f;   //Y轴旋转量
GLuint mvLoc = 0;
GLuint projLoc = 0;
int width, height;
float aspect = 0.f;

glm::mat4 mMat(1.f), vMat(1.f), pMat(1.f), mvMat(1.f);

Torus myTorus(0.5f, 0.2f, 48);
Camera camera(glm::vec3(0.f, 0.f, 5.f));
float deltaTime = 0.f;
float lastFrame = 0.f;

GLboolean keys[1024] = { GL_FALSE };
GLboolean firstMouse = GL_TRUE;

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

void processKeyInput(GLFWwindow* window);

void setupVertices(void)
{
	vector<int> ind = myTorus.getIndices();           //获取顶点索引
	vector<glm::vec3> vert = myTorus.getVertices();   //得到每个顶点,其中任一个顶点都包含(x, y, z)
	vector<glm::vec2> tex = myTorus.getTexCoords();
	vector<glm::vec3> norm = myTorus.getNormals();
	vector<glm::vec3> sTang = myTorus.getStangents();
	vector<glm::vec3> tTang = myTorus.getTtangents();

	vector<float> pValues;   //顶点位置
	vector<float> tValues;   //纹理坐标
	vector<float> nValues;   //法线坐标

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

		//注意这里纹理坐标是S、T
		tValues.push_back(tex[i].s);   
		tValues.push_back(tex[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, pValues.size() * sizeof(float), &(pValues[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);

	//注意后面我们使用glDrawElements绘制,所以这里必须使用 GL_ELEMENT_ARRAY_BUFFER
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[3]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, ind.size() * sizeof(float), &(ind[0]), GL_STATIC_DRAW);
}

void init(GLFWwindow* window)
{
	renderingProgram = Utils::createShaderProgram("vertShader.glsl", "fragShader.glsl");
	cameraX = 0.f, cameraY = 0.f, cameraZ = 2.f;
	torusLocX = 0.f, torusLocY = 0.f, torusLocZ = -0.5f;

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

	setupVertices();
	torusTextureId = Utils::loadTexture("resources/brick1.jpg");
}

void key_movement_callback()
{
	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);
	}
}

void display(GLFWwindow* window, double currentTime)
{
	//注意如果把GL_DEPTH_BUFFER_BIT写成GL_DEPTH_BUFFER,渲染窗口会出现残影
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClearColor(0.2f, 0.6f, 0.2f, 1.f);

	glUseProgram(renderingProgram);

	//GLfloat currentTimeFrame = glfwGetTime();
	deltaTime = currentTime - lastFrame;
	lastFrame = currentTime;
	

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

	key_movement_callback();

	vMat = camera.GetViewMatrix();
	//vMat = glm::translate(glm::mat4(1.f), glm::vec3(cameraX, cameraY, -cameraZ));
	mMat = glm::translate(glm::mat4(1.f), glm::vec3(torusLocX, torusLocY, torusLocZ));
	mMat = glm::rotate(mMat, toRadins(60.f), glm::vec3(1.f, 0.f, 0.f));
	aspect = (float)screen_width / (float)screen_height;
	pMat = glm::perspective(camera.Zoom, aspect, 0.01f, 1000.f);
	//右乘规则
	mvMat = vMat * mMat;

	//更改一个uniform矩阵变量或数组的值。要更改的uniform变量的位置由location指定,location的值应该由glGetUniformLocation函数返回
	// 将透视矩阵和MV 矩阵复制给相应的统一变量
	/*通过一致变量(uniform修饰的变量)引用将一致变量值传入渲染管线。
	  location : uniform的位置。
	  count : 需要加载数据的数组元素的数量或者需要修改的矩阵的数量。
	  transpose : 指明矩阵是列优先(column major)矩阵(GL_FALSE)还是行优先(row major)矩阵(GL_TRUE)。
	  value : 指向由count个元素的数组的指针。
	*/
	glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvMat));
	glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));

	//处理顶点
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	//指定了渲染时索引值为 index 的顶点属性数组的数据格式和位置
	/*Parameters
	index
		指定要修改的顶点属性的索引值

		size
		指定每个顶点属性的组件数量。必须为1、2、3或者4。初始值为4。(梦维:如position是由3个(x, y, z)组成,而颜色是4个(r, g, b, a))

		type
		指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值为GL_FLOAT。

		normalized
		指定当被访问时,固定点数据值是否应该被归一化(GL_TRUE)或者直接转换为固定点值(GL_FALSE)。

		stride
		指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0。

		pointer
		指定一个指针,指向数组中第一个顶点属性的第一个组件。初始值为0。*/
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	//启用或禁用通用顶点属性数组,参数0索引和着色器中的layout(location = 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, torusTextureId);
	/*glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_NEAREST_MIPMAP_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_NEAREST_MIPMAP_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_NEAREST_MIPMAP_NEAREST);
	glBindTexture(GL_TEXTURE_2D, sunTextureId);*/

	//背面剔除,默认情况下,背面剔除是关闭的
	//glEnable(/*GL_CULL_FACE | */GL_DEPTH_TEST);  //开启背面剔除,注意:这里不能开启深度测试!!!!!! 否则贴图纹理有重叠,不知道为什么?:
	//glEnable(GL_CULL_FACE | GL_DEPTH_TEST);   //GL_CULL_FACE 和 GL_DEPTH_TEST 不能写在一起
	glEnable(GL_CULL_FACE);
	glEnable(GL_DEPTH_TEST);
	glFrontFace(GL_CCW); 
	//glDepthFunc(GL_LEQUAL);
	
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[3]);
	glDrawElements(GL_TRIANGLES, myTorus.getIndices().size(), GL_UNSIGNED_INT, 0);
}

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

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

	double offsetLocX = xPos - lastLocX;
	double offsetLocY = lastLocY - yPos;

	lastLocX = xPos;
	lastLocY = yPos;

	camera.ProcessMouseMovement(offsetLocX, offsetLocY);
}

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


void processKeyInput(GLFWwindow* window)
{
	float currentFrame = glfwGetTime();
	deltaTime = currentFrame - lastFrame;
	lastFrame = currentFrame;

	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
	{
		glfwSetWindowShouldClose(window, GLFW_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_KEY_A)
	{
		camera.ProcessKeyboard(LEFT, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_D))
	{
		camera.ProcessKeyboard(RIGHT, deltaTime);
	}

}

void press_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 (action == GLFW_PRESS)
	{
		keys[key] = GL_TRUE;
	}
	else if (action == GLFW_RELEASE)
	{
		//glfwSetWindowShouldClose(window, GL_FALSE);
		keys[key] = GL_FALSE;
	}
}

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, GL_TRUE);

	GLFWwindow* window = glfwCreateWindow(screen_width, screen_height, "Draw torus", nullptr, nullptr);
	if (!window)
	{
		cout << "GLFW create window failed,invoke glfwCreateWindow()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << endl;
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

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

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

	glfwSwapInterval(1);
	init(window);

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

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


	return 0;
}

源码下载

源码下载地址

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值