计算机图形学 | 实验四:绘制一个球体

计算机图形学——球体、立方体、模型变换 画球体的函数 glutWireSphere(a,b,c);边框球 a是球体的半径(一定要在画布的有效范围之内) b是经度线,c是纬度线(精密程度,一般情况下20以上) 默认颜色是白色,默认中心点坐标(0,0,0) ***保证画布的Z的范围大于球体直径 glutSolidSphere(a,b,c);实体球(a,b,c和上面一样) 正方体 glutWireCube(a);线框 a为正方体的边长,中心点坐标(0,0,0) 模型变换 移动:位置、中心点的坐标从000移动到x,y,z glTr 阅读详情

华中科技大学《计算机图形学》课程

MOOC地址:计算机图形学(HUST)

计算机图形学 | 实验四:绘制一个球体

封装Shader

在正式开始介绍球模型的绘制之前,我们需要将和着色器有关的操作进行封装,使其成为一个工具类,这里不介绍具体实现,仅介绍封装的必要性和使用方法。

  • 为什么要封装Shader
  • 如何使用

为什么要封装Shader

封装后,在应对存在多个着色器程序的渲染流程时,可以更方便使用不同的着色器程序,同时也可以降低代码冗余。

如何使用

如下,传入参数分别为顶点着色器和片元着色器的路径,在封装了Shader类后,我们就可以通过一行代码去创建一个新的着色器对象:

Shader shader("res/shader/task3.vs", "res/shader/task3.fs");

假如我们在绘制时需要切换到某个着色器并且使用它,我们仅需要一行代码:

shader.Use();

假如我们需要向着色器中传入一种类型的值,我们也仅需要一行代码去解决它(name为着色器中的名称,value为你希望设置的值):

SetFloat(string &name, float value);

绘制球模型

在正式绘制球模型之前,我们先来介绍一下读完下面的部分你会了解些什么。

  • 球面顶点遍历
  • 构造三角形图元
  • 开启线框模式
  • 开启面剔除

球面顶点遍历

我们要构造绘制球面的顶点数组,首先需要知道如何遍历球面的所有顶点。

图1-1 球体

图1-2 球体正视图和俯视图

在这幅图中,我们假设P是球体上的任意一点,如何计算这一点的坐标呢?我们可以通过如图所示的α角和β角和半径R来表示这个点的坐标。

如图∠α和球体半径(橙色细线)可以计算出球体上P点的Y轴坐标即R * cos∠α,通过∠α也可获得如图所示蓝线长度,即R * sin∠α,蓝线长度等于绿线长度,然后可以根据绿线长度继续计算出P点z坐标即R * sin∠α * sin∠β和P点x坐标即R* sin∠α * cos∠β。

那么当我们知道了球体上任意一个点都可以由α和β以及半径表示出来。

图1-3 球体微分

我们将0π的α角分为Y_SEGMENTS份,将02π的β角分成X_SEGMENTS份,则球上一个点的α和β角可以表示为π/ Y_SEGMENTS * n和2π/ X_SEGMENTS * m(0<n< Y_SEGMENTS, 0<m<X _SEGMENTS)

这样,通过遍历每一种α和β的组合,可以得到球体表面上离散点的集合。

这一部分就是生成顶点的代码实现,Y_SEGMENTS和X_SEGMENTS表示将α和β分割了多少份,y和x表示分别是第几份,以此进行遍历,xSegment * 2.0f * PI即β角,ySegment * PI即α角。

// 生成球的顶点
for (int y = 0; y <= Y_SEGMENTS; y++)
{
	for (int x = 0; x <= X_SEGMENTS; x++)
	{
		float xSegment = (float)x / (float)X_SEGMENTS;
		float ySegment = (float)y / (float)Y_SEGMENTS;
		float xPos = std::cos(xSegment * 2.0f * PI) * std::sin(ySegment * PI);
		float yPos = std::cos(ySegment * PI);
		float zPos = std::sin(xSegment * 2.0f * PI) * std::sin(ySegment * PI);

		sphereVertices.push_back(xPos);
		sphereVertices.push_back(yPos);
		sphereVertices.push_back(zPos);
	}
}

需要注意的是,在横向分割时,n=0和n= X_SEGMENTS是位置相同的点,如果后期需要加载纹理则不能随意将之舍去,所以顶点总数实际上是(X_SEGMENTS + 1) * (Y_SEGMENTS+1)。

构造三角形图元

由于OpenGL中是以三角形为基本图元进行绘制的,所以在我们得到了球面遍历的顶点数组后,我们需要扩充顶点,构造成基本的三角形图元。

图2-1 顶点扩充

图2-2 球体扩充效果

我们会将对遍历球面顶点数组的每个顶点,将其扩充为两个三角形,除去最后一行顶点和每一行最后一个点外,每一个顶点都会扩充成六个顶点,原数组一共有(X_SEGMENTS+1) * (Y_SEGMENTS+1)个顶点,扩充后有X_SEGMENTS*Y_SEGMENTS * 6个顶点,这里我们使用索引数组去构造三角形图元。

实现代码如下:

	// 根据球面上每一点的坐标,去构造一个三角形顶点数组
	for (int i = 0; i < Y_SEGMENTS; i++)
	{
		for (int j = 0; j < X_SEGMENTS; j++)
		{

			sphereIndices.push_back(i * (X_SEGMENTS + 1) + j);
			sphereIndices.push_back((i + 1) * (X_SEGMENTS + 1) + j);
			sphereIndices.push_back((i + 1) * (X_SEGMENTS + 1) + j + 1);

			sphereIndices.push_back(i * (X_SEGMENTS + 1) + j);
			sphereIndices.push_back((i + 1) * (X_SEGMENTS + 1) + j + 1);
			sphereIndices.push_back(i * (X_SEGMENTS + 1) + j + 1);
		}
	}

开启线框模式

为了观察我们绘制的球模型的顶点是否存在错误,由于opengl中默认的绘制方式为填充模式,所以我们需要改填充模式为线框模式,这样可以更好的检查绘制结果

如图为填充模式和线框模式的区别(左图为填充模式,右图为线框模式)。

图3-1 填充模式和线框模式效果对比

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //使用线框模式绘制

开启面剔除

由于OpenGL中绘制时会同时绘制正面和背面,并且我们开启了线框模式后,并不能通过深度测试将背面遮挡住,所以我们需要开启面剔除。来将背面剔除,面剔除主要是剔除顶点绕法为顺时针的面。

如左下图,为开启面剔除后,将背面剔除的结果。

图4-1 填充模式和线框模式效果对比

同样的,代码中我们只需要开启面剔除,并指定剔除面即可,GL_FRONT为剔除正面,GL_BACK为剔除背面。

以下为代码实现:

// 开启面剔除(只需要展示一个面,否则会有重合)
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);

最后

当做好了以上的步骤之后,我们可以看到下面的结果。

在这里插入图片描述

开启线框模式:

在这里插入图片描述

完整代码

shader.h:

#pragma once
#ifndef __SHADER_H__
#define __SHADER_H__

#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "string"

class Shader
{
public:
	unsigned int ID;

	Shader(const GLchar* vertex_shader_path, const GLchar* fragment_shader_path);
	~Shader();

	void Use();
	void SetBool(const std::string &name, bool value) const;
	void SetInt(const std::string &name, int value) const;
	void SetFloat(const std::string &name, float value) const;
	void SetVec2(const std::string &name, const glm::vec2 &value) const;
	void SetVec2(const std::string &name, float x, float y) const;
	void SetVec3(const std::string &name, const glm::vec3 &value) const;
	void SetVec3(const std::string &name, float x, float y, float z) const;
	void SetVec4(const std::string &name, const glm::vec4 &value) const;
	void SetVec4(const std::string &name, float x, float y, float z, float w) const;
	void SetMat2(const std::string &name, const glm::mat2 &value) const;
	void SetMat3(const std::string &name, const glm::mat3 &value) const;
	void SetMat4(const std::string &name, const glm::mat4 &value) const;

private:
	int GetShaderFromFile(const GLchar* vertex_shader_path, const GLchar* fragment_shader_path,
		std::string *vertex_shader_code, std::string *fragment_shader_code);
	int LinkShader(const char* vertex_shader_code, const char* fragment_shader_code);
	int GetUniform(const std::string &name) const;
	void CheckCompileErrors(GLuint shader, std::string type);
};

#endif // !__SHADER_H__

shader.cpp:

#include "shader.h"
#include "fstream"
#include "sstream"
#include "iostream"

Shader::Shader(const GLchar *vertex_shader_path, const GLchar *fragment_shader_path)
{
	std::string vertex_shader_code;
	std::string fragment_shader_code;
	if (GetShaderFromFile(vertex_shader_path, fragment_shader_path, &vertex_shader_code, &fragment_shader_code))
	{
		return;
	}
	if (LinkShader(vertex_shader_code.c_str(), fragment_shader_code.c_str()))
	{
		return;
	}
}

Shader::~Shader()
{
}

void Shader::Use()
{
	glUseProgram(ID);
}

void Shader::SetBool(const std::string &name, bool value) const
{
	SetInt(name, (int)value);
}

void Shader::SetInt(const std::string &name, int value) const
{
	glUniform1i(GetUniform(name), value);
}

void Shader::SetFloat(const std::string &name, float value) const
{
	glUniform1f(GetUniform(name), value);
}

void Shader::SetVec2(const std::string &name, float x, float y) const
{
	glUniform2f(GetUniform(name), x, y);
}

void Shader::SetVec2(const std::string &name, const glm::vec2 &value) const
{
	SetVec2(name, value.x, value.y);
}

void Shader::SetVec3(const std::string &name, float x, float y, float z) const
{
	glUniform3f(GetUniform(name), x, y, z);
}

void Shader::SetVec3(const std::string &name, const glm::vec3 &value) const
{
	SetVec3(name, value.x, value.y, value.z);
}

void Shader::SetVec4(const std::string &name, float x, float y, float z, float w) const
{
	glUniform4f(GetUniform(name), x, y, z, w);
}

void Shader::SetVec4(const std::string &name, const glm::vec4 &value) const
{
	SetVec4(name, value.x, value.y, value.z, value.w);
}

void Shader::SetMat2(const std::string &name, const glm::mat2 &value) const
{
	glUniformMatrix2fv(GetUniform(name), 1, GL_FALSE, &value[0][0]);
}

void Shader::SetMat3(const std::string &name, const glm::mat3 &value) const
{
	glUniformMatrix3fv(GetUniform(name), 1, GL_FALSE, &value[0][0]);
}

void Shader::SetMat4(const std::string &name, const glm::mat4 &value) const
{
	glUniformMatrix4fv(GetUniform(name), 1, GL_FALSE, &value[0][0]);
}

int Shader::GetShaderFromFile(const GLchar *vertex_shader_path, const GLchar *fragment_shader_path, std::string *vertex_shader_code, std::string *fragment_shader_code)
{
	std::ifstream vertex_shader_file;
	std::ifstream fragment_shader_file;
	vertex_shader_file.exceptions(std::ifstream::badbit | std::ifstream::failbit);
	fragment_shader_file.exceptions(std::ifstream::badbit | std::ifstream::failbit);
	try
	{
		vertex_shader_file.open(vertex_shader_path);
		fragment_shader_file.open(fragment_shader_path);
		std::stringstream vertex_shader_stream, fragment_shader_stream;
		vertex_shader_stream << vertex_shader_file.rdbuf();
		fragment_shader_stream << fragment_shader_file.rdbuf();
		vertex_shader_file.close();
		fragment_shader_file.close();
		*vertex_shader_code = vertex_shader_stream.str();
		*fragment_shader_code = fragment_shader_stream.str();
	}
	catch (std::ifstream::failure e)
	{
		std::cout << "Load Shader File Error!" << std::endl;
		return -1;
	}
	return 0;
}

int Shader::LinkShader(const char *vertex_shader_code, const char *fragment_shader_code)
{
	int vertex_shader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertex_shader, 1, &vertex_shader_code, NULL);
	glCompileShader(vertex_shader);
	CheckCompileErrors(vertex_shader, "VERTEX");

	int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragment_shader, 1, &fragment_shader_code, NULL);
	glCompileShader(fragment_shader);
	CheckCompileErrors(fragment_shader, "FRAGMENT");

	this->ID = glCreateProgram();
	glAttachShader(ID, vertex_shader);
	glAttachShader(ID, fragment_shader);
	glLinkProgram(ID);
	CheckCompileErrors(ID, "PROGRAM");

	glDeleteShader(vertex_shader);
	glDeleteShader(fragment_shader);
	return 0;
}

int Shader::GetUniform(const std::string &name) const
{
	int position = glGetUniformLocation(ID, name.c_str());
	if (position == -1)
	{
		std::cout << "uniform " << name << " set failed!" << std::endl;
	}
	return position;
}

void Shader::CheckCompileErrors(GLuint shader, std::string type)
{
	GLint success;
	GLchar infoLog[512];
	if (type == "PROGRAM")
	{
		glGetProgramiv(shader, GL_LINK_STATUS, &success);
		if (!success)
		{
			glGetProgramInfoLog(shader, 512, NULL, infoLog);
			std::cout << "ERROR::PROGRAM_LINKING_ERROR!\n"
				<< infoLog << std::endl;
		}
	}
	else
	{
		glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
		if (!success)
		{
			glGetShaderInfoLog(shader, 512, NULL, infoLog);
			std::cout << "ERROR::SHADER::" << type << "::COMPILATION_FAILED\n"
				<< infoLog << std::endl;
		}
	}
}

main.cpp:

/***
* 例程  绘制球体 (MAKE后运行时可删除ALL_BUILD,也可以将Task-sphere设为默认启动工程)
* 步骤:
* 1-初始化:       GLFW窗口,GLAD。
* 2-计算球体顶点:通过数学方法计算球体的每个顶点坐标
* 2-数据处理:     通过球体顶点坐标构造三角形网格,生成并绑定VAO&VBO&EBO(准备在GPU中进行处理),设置顶点属性指针(本质上就是告诉OpenGL如何处理数据)。
* 3-着色器:       给出顶点和片段着色器,然后链接为着色器程序,渲染时使用着色器程序。
* 4-渲染:         使用画线模式画圆,开启面剔除,剔除背面,使用线框模式画球
* 5-结束:        清空缓冲,交换缓冲区检查触发事件后释放资源
*/

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "shader.h"
#include <iostream>
#include <math.h>
#include <vector>

const unsigned int screen_width = 780;
const unsigned int screen_height = 780;

const GLfloat PI = 3.14159265358979323846f;

// 将球横纵划分成50X50的网格
const int Y_SEGMENTS = 50;
const int X_SEGMENTS = 50;

int main()
{
	// 初始化GLFW
	glfwInit();                                    // 初始化GLFW
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // OpenGL版本为3.3,主次版本号均设为3
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 使用核心模式(无需向后兼容性)
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);           // 如果使用的是Mac OS X系统,需加上这行
	glfwWindowHint(GLFW_RESIZABLE, false);                         // 不可改变窗口大小

																   // 创建窗口(宽、高、窗口名称)
	auto window = glfwCreateWindow(screen_width, screen_height, "Sphere", nullptr, nullptr);
	if (window == nullptr)
	{ // 如果窗口创建失败,输出Failed to Create OpenGL Context
		std::cout << "Failed to Create OpenGL Context" << std::endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window); // 将窗口的上下文设置为当前线程的主上下文

									// 初始化GLAD,加载OpenGL函数指针地址的函数
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}

	// 指定当前视口尺寸(前两个参数为左下角位置,后两个参数是渲染窗口宽、高)
	glViewport(0, 0, screen_width, screen_height);

	Shader shader("res/shader/task3.vs", "res/shader/task3.fs"); // 加载着色器

	std::vector<float> sphereVertices;
	std::vector<int> sphereIndices;

	// 生成球的顶点
	for (int y = 0; y <= Y_SEGMENTS; y++)
	{
		for (int x = 0; x <= X_SEGMENTS; x++)
		{
			float xSegment = (float)x / (float)X_SEGMENTS;
			float ySegment = (float)y / (float)Y_SEGMENTS;
			float xPos = std::cos(xSegment * 2.0f * PI) * std::sin(ySegment * PI);
			float yPos = std::cos(ySegment * PI);
			float zPos = std::sin(xSegment * 2.0f * PI) * std::sin(ySegment * PI);

			sphereVertices.push_back(xPos);
			sphereVertices.push_back(yPos);
			sphereVertices.push_back(zPos);
		}
	}

	// 根据球面上每一点的坐标,去构造一个三角形顶点数组
	for (int i = 0; i < Y_SEGMENTS; i++)
	{
		for (int j = 0; j < X_SEGMENTS; j++)
		{

			sphereIndices.push_back(i * (X_SEGMENTS + 1) + j);
			sphereIndices.push_back((i + 1) * (X_SEGMENTS + 1) + j);
			sphereIndices.push_back((i + 1) * (X_SEGMENTS + 1) + j + 1);

			sphereIndices.push_back(i * (X_SEGMENTS + 1) + j);
			sphereIndices.push_back((i + 1) * (X_SEGMENTS + 1) + j + 1);
			sphereIndices.push_back(i * (X_SEGMENTS + 1) + j + 1);
		}
	}

	// 球
	unsigned int VBO, VAO;
	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);
	// 生成并绑定球体的VAO和VBO
	glBindVertexArray(VAO);

	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	// 将顶点数据绑定至当前默认的缓冲中
	glBufferData(GL_ARRAY_BUFFER, sphereVertices.size() * sizeof(float), &sphereVertices[0], GL_STATIC_DRAW);

	GLuint element_buffer_object; // EBO
	glGenBuffers(1, &element_buffer_object);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer_object);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sphereIndices.size() * sizeof(int), &sphereIndices[0], GL_STATIC_DRAW);

	// 设置顶点属性指针
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
	glEnableVertexAttribArray(0);

	// 解绑VAO和VBO
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);

	// 渲染循环
	while (!glfwWindowShouldClose(window))
	{
		// 清空颜色缓冲
		glClearColor(0.0f, 0.34f, 0.57f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		shader.Use();
		// 绘制球
		// 开启面剔除(只需要展示一个面,否则会有重合)
		glEnable(GL_CULL_FACE);
		glCullFace(GL_BACK);
		glBindVertexArray(VAO);
		// 使用线框模式绘制
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
		glDrawElements(GL_TRIANGLES, X_SEGMENTS * Y_SEGMENTS * 6, GL_UNSIGNED_INT, 0);
		// 点阵模式绘制
		// glPointSize(5);
		// glDrawElements(GL_POINTS, X_SEGMENTS*Y_SEGMENTS*6, GL_UNSIGNED_INT, 0);
		// 交换缓冲并且检查是否有触发事件(比如键盘输入、鼠标移动等)
		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	// 删除VAO和VBO,EBO
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	glDeleteBuffers(1, &element_buffer_object);

	// 清理所有的资源并正确退出程序
	glfwTerminate();
	return 0;
}
std::cosh、std::cos、std::sin、std::sinh的介绍和在复数运算中的举例 std::coshstd::cosstd::sinstd::sinh是 C++ 标准库中的数学函数,用于计算。下面是对这些函数的解释及简单的示例代码。 阅读详情

相关推荐

计算机图形学实验四球体 Gouraud 光照模型

实验目的 (1)掌握双线性光强插值模型。 二、实验步骤 (1)建立三维坐标系 Oxyz,原点位于屏幕客户区中心,x 轴水平向右为正, y 轴铅直向上为正,z 轴垂直于屏幕指向观察者。 (2)绘制体心和坐标系中心重合的球体表面,使用 ZBuffer 消隐算法进行消 隐。使用 Z‐Buffer 算法对球面进行深度消隐,然后使用有效边表算法进行填充。 为了减少渲染的面片数,先使用凸多面体消隐...

NuvoleSiene的博客 8343

C++ cmath头文件

C++中cmath头文件 <math.h>是C标准函数库中的头文件。在C++中一般用。此头文件中声明了一系列函数来计算常见的数学运算和变换: std::abs: 计算绝对值,包括整数类型; std::fabs: 计算绝对值,不包括整数类型; std::fma(x,y,z):x*y+z; std::sin: 正弦; std::asin: 反正弦; std::sinh: 双曲正弦; std::asinh: 双曲反正弦; std::cos: 余弦; std::acos: 反正弦; std::cosh:

m0_51799445的博客 6754

孔令德的计算机图形学课程实验

授课总学时64,实验项目学时12  实验一  绘制任意斜率的直线(2学时)        验证性 实验内容:利用中点Bresenham算法,编程实现绘制任意斜率的直线。 基本要求: 1. 掌握中点Bresenham算法的原理和算法; 2. 使用鼠标在屏幕上绘制任意斜率的直线; 实验拓展:彩色直线与反走样直线。   实验二  交互式绘制多边形(2学时)  

klingde的专栏 1万+

计算机图形学练习(四)——画球

以线框模式画一个球,可由鼠标键盘控制 ball.cpp #include <iostream> // GLEW #define GLEW_STATIC #include <GL/glew.h> // GLFW #include <GLFW/glfw3.h> //glm #include "glm/glm.hpp" #include "glm/gtc/matrix_transform.hpp" #include "glm/gtc/type_ptr.hpp" #incl

qq_44018760的博客 1622

计算机图形学-切割球体

#include <stdio.h> #include <gl/glut.h> #include <math.h> #include "gmath.h" #include "gmatrix3d.h" #include "gvector3d.h" #include "gcamera.h" #include "gmaterial.h" #include "gligh...

qq_37165724的博客 1002

OpenGL+WebGL——绘制球体

编写C++程序main.cpp,包括构建点的数据结构、计算球体的参数、绘制球面、初始化设置、绘图函数与主函数调用 #include <GL\glut.h> #include <math.h> #define PI 3.14159265358979323846 #define PI2 6.28318530717958647692 GLsizei width = 600,...

大太阳 2483

计算机图形学(五)——opengl实现MFC界面下的三维球体的绘制

先上效果图 通过坐标的控件可以控制球体的移动,可以设置是否有光照及实体图,还可控制球的大小和球面级数 1.球体的绘制 void Cm03qiuView::DrawGeometry() { //在此处画球体 GLfloat r = (GLfloat)m_nRadius; GLfloat vdata[6][3] = { //初始点坐标 {r,0.0,0.0},{-r,0.0,0.0}, ...

诶你爱我吗的博客 4911

计算机图形学——光线追踪

计算机图形学——光线追踪         参考资料 :用JavaScript玩转计算机图形学         实验内容:使用光线追踪进行场景渲染。      实验效果:       1、简介      光线跟踪(ray tracing)是一个在二维(2D)屏幕上呈现三维(3D)图像的方法。从摄影机的位置,通过影像平面上的像素位置(比较正确的说法是取样(sampling)位置),发射一束

小黄鸭的博客 5878

[OpenGL]计算机图形学实验01:一个简单的球体

#include #include #include #define PI 3.14 void myDisplay2(){ //画两个顶端的圆形区域 glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); glBegin(GL_TRIANGLE_FAN); glVertex3d(0.0,0.0,1.0); double c = PI/180; fl

汪海的实验室 6356

2022年山东科技大学计算机图形学实验代码(基础代码)(可直接运行)

2022年山东科技大学计算机图形学实验代码(基础代码)(可直接运行) 包括: 绘制任意斜率的直线段 交互式绘制多边形 二维几何变换 直线段裁剪 立方体线框模型正交投影 立方体线框模型透视投影 动态三视图 动态绘制Bezier曲线 交互式三次B样条曲线 旋转的Koch雪花 颜色渐变立方体 地理划分线框球 交叉条消隐 立方体光照模型 球体Gouraud光照模型 球体Phong光照模型 立方体纹理映射

ArcGIS Pro中协同区位熵方法在商业选址分析中的应用

本文详细介绍了如何利用ArcGIS Pro中的协同区位熵方法进行科学的商业选址分析。该方法通过量化目标客户与竞争对手在空间上的关联程度,精准识别市场空白区与竞争红海,帮助决策者从“凭感觉”转向“用数据说话”,有效提升选址成功率和投资回报。

weixin_29214559的博客 362

计算机图形学OpenGL实验——实现三维空间、视野方向转换

计算机图形学实验,用OpenGL实现三维空间,绘制三维房间、家具、房屋建筑等。 用到的OpenGL 函数 glColor3f(blue); //设置颜色 glutSolidCube(size);//绘制正方体 glVertex3f(x, y, z);//设置点坐标 glLightfv(a,b,c); //设置光源 glTranslatef(x, y, z`)`;//平移函数 gl...

weixin_43576525的博客 1万+

SAP BTP开发入门:从PaaS到CAP/UI5的30天学习路线

在云计算与数字化转型的大背景下,企业系统集成与云端扩展需求激增,传统的单点开发模式正面临深刻变革。PaaS(平台即服务)作为云原生的核心概念,将基础设施、开发环境与应用服务统一封装,为企业提供了灵活的扩展能力。SAP BTP正是SAP生态中的PaaS平台,它承载着系统集成、低代码开发、AI服务与数据管理,成为连接S/4HANA等核心业务系统与创新应用的桥梁。对于ABAP开发者而言,掌握BTP不仅是技能升级,更是应对从传统部署向云端订阅模式转型的必由之路。本文从平台基础出发,梳理BTP的核心服务与开发模型(如

weixin_31766003的博客 286

VTK开发笔记(三):熟悉VTK开发流程,编写球体,多半透明球体Demo

开始vtk实战,了解vtk的一些基本框架,通过代码是最好的方式。本篇实现一个vtk实现多球体半透明的Demo。

长沙红胖子 Qt・西安|省级科研团队从业背景,深耕双一流体系高精尖技术配套研发|剥离高精尖机理,沉淀高端特种行业领域 Qt 工程化落地经验|博文仅分享通用技术总结,输出公开普适工程思路。 9784

ImageNet分类实战:用PyTorch复现AlexNet的5个关键技巧(附代码)

本文详细介绍了使用PyTorch复现经典AlexNet模型进行ImageNet图像分类的五个关键工程技巧。内容涵盖模型架构的现代重构、训练策略优化、核心组件实现与替代方案,以及实用的训练调试方法,并提供了完整的代码示例,帮助开发者深入理解深度卷积神经网络的实现细节与优化思路。

i0j1k2l3m的博客 94

实战避坑:示波器测量非隔离开关电源的炸机风险与隔离方案

本文详细分析了使用示波器测量非隔离开关电源时的炸机风险,揭示了地线环路导致的短路问题,并对比了四种防炸机解决方案,包括示波器隔离供电、拔掉电源地线、使用差分探头和被测板隔离供电。重点推荐使用隔离变压器方案,确保测量安全与精度,同时提供了实操建议与经验分享,帮助工程师避免常见测量事故。

weixin_29224309的博客 564

计算机图形学实验四真实感图形的绘制

真实感图形的绘制一级目录 一级目录

qq_52497285的博客 4425

Qt快速读取Excel文件

网上很多读取方式都是如下形式,太慢了,打开文件+读取文件要6s以上,实在是受不了! QAxObject excel("Excel.Application"); excel.setProperty("Visible", false); QAxObject *work_books = excel.querySubObject("WorkBooks"); work_boo...

c+c++的博客 2万+

【计算机图形学】实验4 :OpenGL绘制分子模型

本文主要是计算机图形学实验4,即 OpenGL绘制分子模型,属于计算机图形学实验专栏

superiony的博客 864

用STM32F103C8T6和TB6612驱动模块,从零搭建一辆能避障循迹的智能小车(附完整代码)

本文详细介绍了如何使用STM32F103C8T6和TB6612驱动模块从零搭建一辆能避障循迹的智能小车。内容涵盖硬件选型、电路设计、底层驱动配置以及智能行为算法实现,并附有完整代码示例,帮助开发者快速掌握嵌入式开发的核心技术。

weixin_42641741的博客 447

基于FPGA的超声成像算法的硬件设计

顶层设计如下图: 1. Verilog的硬件设计型号是 ALTERA 2.数据的输入量已经给出,附上的四个矩阵输入都要实现。 3.波束形成部分要在FPGA上完成,最后的matlab的代码部分只是获取数据后的图像显示 4.不需要动态聚焦,只是完成固定的四个不同输入数据的显示即可 5.不需要实物,但要实现硬件的仿真,要有相应的模块图和结构图,类似如下 具体实现过程和最终结果如下: 定义aperture(孔径)大小————输入量,数据已给出,一共四个规格的ape...

FPGA/MATLAB学习教程/源码/项目合作开发 1万+

SUES计算机图形学实验代码-实验八球体光照模型与凹凸纹理映射:深入解析球体渲染之美

SUES计算机图形学实验代码-实验八球体光照模型与凹凸纹理映射:深入解析球体渲染之美 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 在计算机图形学领域,如何真实地模拟物体表面的光照效果与纹理细节一直是研究的重点。SUES计算机图形学实验代码-实验八:球体光照模型与凹凸纹理映射,正是针对这一领域精心设计的实验项目。该项目旨在帮助学习者深入理解球体光照模型和凹凸纹理映射的...

gitblog_06789的博客 278

《唤醒你的AI同事:WorkBuddy从零上手》000:介绍及目录

《唤醒你的AI同事:WorkBuddy从零上手》全书导览与总目录:000–043 共 44 篇,覆盖从环境搭建、对话基础到资料库、行业助手与多模态生成的入门实战。含完整篇目速查与编号直达,建议关注收藏。

LuckyHanMo的博客 606

计算机图形学

计算机图形学

ProgramNovice的博客 662

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

OpenGL进阶(四)-用参数方程绘制椭球体

首先参考这篇文章绘制一个球体:OpenGL 用参数方程绘制球 我们知道球体的参数方程是这样的: x=r·sin(α)·cos(β) y=r·sin(α)·sin(β) z=r·cos(α) 椭圆的参数方程是: x=rx·sin(α)·cos(β) y=ry·sin(α)·sin(β) z=rz·cos(α) 在这个基础上进行一些修改就可以实现椭圆的绘制了! 代码实现如下

爱冒险的技术宅 1万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

SUES计算机图形学实验代码 - 实验八:球体光照模型与凹凸纹理映射

SUES计算机图形学实验代码 - 实验八:球体光照模型与凹凸纹理映射 去发现同类优质开源项目:https://gitcode.com/ 本文档包含《计算机图形学 - 孔令德Visual Studio的MFC教材》中实验八的补充实验代码。该实验主要研究球体光照模型以及凹凸纹理映射的相关实现。 实验内容 球体光照模型:通过设置不同的光照参数,观察球体表面的光照效果。 凹凸纹理映射:利用纹理映射技术,...

gitblog_06720的博客 300

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

上一篇: 计算机图形学 | 探秘造型技术
下一篇: 【《C Primer Plus》读书笔记】第14章:结构和其他数据形式
UestcXiye
博客等级 码龄8年 9032粉丝 1306原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值