openGL绘制带纹理太阳、地球、月亮,并且地球自转并且围绕太阳旋转。月亮自转也会围绕地球旋转

openGL系列文章目录

前言

  使用openGL绘制太阳、地球、月亮,太阳自转,地球自转并且围绕太阳旋转。月亮自转也会围绕地球旋转,其实月亮也会围绕太阳旋转的。

一、效果

在这里插入图片描述
还是有不满意的地方:
1.没有添加星空盒子
如果加上星空背景效果会好很多
2.贴图是我自己ps的,在太阳和月亮上有重合问题

二、实现思路

1.太阳、地球、月亮使用球体代替
2.我们的行星地球围绕太阳旋转的方式,以及月球围绕地球旋转的方式。
使用矩阵堆栈轻松地完成此操作。顾名思义,矩阵堆栈是一堆变换
矩阵。正如我们将看到的,矩阵堆栈使得创建和管理复杂的分层对象和场景变得容易,它
使得变换可以构建在其他变换之上(或者从其他变换中被移除)。
3. 太阳、地球、月亮纹理贴图

主要代码

main.cpp主程序


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

using namespace std;

static const int screen_width = 1920;
static const int screen_height = 1080;
int width = 0;
int height = 0;

GLuint renderingProgram = 0;

static const int numberVAOs = 1;
static const int numberVBOs = 3;
GLuint vao[numberVAOs] = { 0 };
GLuint vbo[numberVBOs] = { 0 };

float cameraLocX = 0.f, cameraLocY = 0.f, cameraLocZ = 0.f;
float sunLocX = 0.f, sunLocY = 0.f, sunLocZ = 0.f;
float earthLocX = 0.f, earthLocY = 0.f, earthLocZ = 0.f;
float moonLocX = 0.f, moonLocY = 0.f, moonLocZ = 0.f;
float aspect = 0.f;
int mvLoc = 0;
int projLoc = 0;
float rotAmt = 0.f;

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

//vector<glm::mat4> mvStack;

GLuint sunTextureId = 0, earthTextureId = 0, moonTextureId = 0;

Sphere sun = Sphere(48);
Sphere earth = Sphere(48);
Sphere moon = Sphere(48);

GLboolean keys[1024] = { GL_FALSE };

Camera camera(glm::vec3(0.f, 0.f, 5.f));
GLfloat lastFrame = 0.0f;
GLfloat deltaTime = 0.0f;

GLboolean firstMouse = GL_TRUE;
GLfloat lastX = 0.f;
GLfloat lastY = 0.f;

std::stack<glm::mat4> mvStack;  //注意不要和vsctor<glm::mat4>相混淆


void setupVertices()
{
	vector<int> ind = sun.getIndices();
	vector<glm::vec3> vert = sun.getVertices();
	vector<glm::vec2> text = sun.getTexCoords();
	vector<glm::vec3> norm = sun.getNormals();
	vector<glm::vec3> tang = sun.getTangents();

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

	int numIndices = sun.getNumIndices();
	for (int i = 0; i < numIndices; i++)
	{
		//pValues.push_back(vert[ind[i]].x);
		pValues.push_back((vert[ind[i]]).x);
		pValues.push_back((vert[ind[i]]).y);
		pValues.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);
	}

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

	glGenBuffers(numberVBOs, vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	size_t sizeFloat = sizeof(float);
	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);
}

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;
	}
}

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 mouse_move_callback(GLFWwindow* window, double xPos, double yPos)
{
	if (firstMouse)
	{
		lastX = xPos;
		lastY = yPos;
		firstMouse = GL_FALSE;
	}

	GLfloat xOffset = xPos - lastX;
	GLfloat yOffset = lastY - yPos;

	lastX = xPos;
	lastY = yPos;

	camera.ProcessMouseMovement(xOffset, yOffset);
}

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

void init(GLFWwindow* window)
{
	renderingProgram = Utils::createShaderProgram("vertShader.glsl", "fragShader.glsl");
	glfwGetFramebufferSize(window, &width, &height);
	aspect = (float)width / (float)height;
	pMat = glm::perspective(glm::radians(45.f), aspect, 0.01f, 1000.f);
	glfwGetFramebufferSize(window, &width, &height);


	setupVertices();

	sunTextureId = Utils::loadTexture("resource/shining.jpg");
	earthTextureId = Utils::loadTexture("resource/earth.jpg");
	moonTextureId = Utils::loadTexture("resource/moon.jpg");
}


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

	//必不可少!!!否则窗口是黑的,不会渲染任何东西
	glUseProgram(renderingProgram);

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

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

	key_movement_callback();

	//移动相机矩阵:这里必须是-cameraZ,否则相机看不到球体
	//vMat = glm::translate(glm::mat4(1.f), glm::vec3(cameraX, cameraY, -cameraZ));
	vMat = camera.GetViewMatrix();
	/*sunLocZ = -6.f;*/
	mMat = glm::translate(glm::mat4(1.f), glm::vec3(sunLocX, sunLocY, sunLocZ));
	mMat = glm::rotate(glm::mat4(1.f), currentTime * 0.1f, glm::vec3(0.f, 1.f, 0.f));
	pMat = glm::perspective(camera.Zoom, (GLfloat)screen_width / (GLfloat)screen_height, 0.01f, 1000.f);

	//右乘规则
	//mvMat = mMat * vMat;   //金字塔会离开视口
	mvMat = vMat * mMat;

	//将视图矩阵压入堆栈
	mvStack.push(vMat);

	//更改一个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));

	// ----------------------  sun
	/*堆栈顶部的矩阵复制一份,并和其他的变换结合,然后再利用这个命令把新的矩阵副本推入堆栈中。
	*/
	mvStack.push(mvStack.top());
	//向矩阵堆栈顶部的矩阵添加平移
	mvStack.top() *= glm::translate(glm::mat4(1.f), glm::vec3(0.f, 0.f, 0.f));
	mvStack.push(mvStack.top());
	//在不移除的情况下,返回堆栈最顶部旋转矩阵(绕X轴)的引用。
	mvStack.top() *= glm::rotate(glm::mat4(1.f), (float)glfwGetTime() * 0.4f, glm::vec3(0.f, 1.f, 0.f));
	glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvStack.top()));

	//绑定到太阳顶点缓冲区
	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);

	//激活纹理坐标 
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, sunTextureId);

	/*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);
	//glFrontFace(GL_CCW);

	glDrawArrays(GL_TRIANGLES, 0, sun.getNumIndices());
	mvStack.pop();


	/**********************************   earth           */
	//复制一份堆栈顶部矩阵压入堆栈
	/*push():在堆栈顶部创建一个新的条目。我们通常会把目前在堆栈顶部的矩阵复制一份,
	  并和其他的变换结合,然后再利用这个命令把新的矩阵副本推入堆栈中。
	*/
	//top():在不移除的情况下,返回堆栈最顶部矩阵的引用。
	mvStack.push(mvStack.top());
	mvStack.top() *= glm::translate(glm::mat4(1.f), glm::vec3(glm::sin((float)currentTime) * 2.5f, glm::cos((float)currentTime) * 0.4, glm::cos((float)currentTime) * 0.5f));
	mvStack.push(mvStack.top());
	//地球绕太阳旋转,即绕Y轴旋转
	mvStack.top() *= glm::rotate(glm::mat4(1.f), (float)currentTime, glm::vec3(0.f, 1.f, 0.f));
	mvStack.top() *= glm::scale(glm::mat4(1.f), glm::vec3(0.4f));
	//更改一个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(mvStack.top()));
	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);

	//绑定到地球纹理坐标缓冲区
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, earthTextureId);
	//背面剔除,默认情况下,背面剔除是关闭的
	glEnable(GL_CULL_FACE);
	glFrontFace(GL_CCW);

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glDrawArrays(GL_TRIANGLES, 0, earth.getNumIndices());
	mvStack.pop();
	mvStack.pop();


	/****************************************   moon */
	//复制一份堆栈顶部矩阵压入堆栈
	/*push():在堆栈顶部创建一个新的条目。我们通常会把目前在堆栈顶部的矩阵复制一份,
	  并和其他的变换结合,然后再利用这个命令把新的矩阵副本推入堆栈中。
	*/
	//top():在不移除的情况下,返回堆栈最顶部矩阵的引用。
	mvStack.push(mvStack.top());
	mvStack.top() *= glm::translate(glm::mat4(1.f), glm::vec3(glm::sin((float)currentTime) * 3.f, glm::cos((float)currentTime) * 0.8f, glm::cos((float)currentTime) * 3.0f));
	mvStack.push(mvStack.top());
	//月球绕地球旋转,即绕Y轴旋转
	mvStack.top() *= glm::rotate(glm::mat4(1.f), (float)currentTime * 4.f, glm::vec3(0.f, 1.f, 0.f));
	mvStack.top() *= glm::scale(glm::mat4(1.f), glm::vec3(0.2f));
	//更改一个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(mvStack.top()));
	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);
	//绑定到地球纹理坐标缓冲区
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, moonTextureId);

	//背面剔除,默认情况下,背面剔除是关闭的
	glEnable(GL_CULL_FACE | GL_DEPTH_TEST);
	glFrontFace(GL_CCW);
	glDepthFunc(GL_LEQUAL);
	glDrawArrays(GL_TRIANGLES, 0, moon.getNumIndices());
	mvStack.pop();
	mvStack.pop();
	mvStack.pop();


	星空盒
	//GLfloat skyboxVertices[] = {
	//	// Positions          
	//	-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
	//};

	//GLuint skyboxVAO, skyboxVBO;
	//glGenVertexArrays(1, &skyboxVAO);
	//glGenBuffers(1, &skyboxVBO);
	//glBindVertexArray(skyboxVAO);
	//glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
	//glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);

	//glEnableVertexAttribArray(0);
	//glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
	//glBindVertexArray(0);

	//vector<const GLchar*> faces;
	//faces.push_back("resource/right.jpg");
	//faces.push_back("resource/left.jpg");
	//faces.push_back("resource/top.jpg");
	//faces.push_back("resource/bottom.jpg");
	//faces.push_back("resource/front.jpg");
	//faces.push_back("resource/back.jpg");

}

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);
}

// Loads a cubemap texture from 6 individual texture faces
// Order should be:
// +X (right)
// -X (left)
// +Y (top)
// -Y (bottom)
// +Z (front)
// -Z (back)
GLuint loadCubemap(vector<const GLchar*> faces)
{
	GLuint textureId;
	glGenTextures(1, &textureId);
	glBindTexture(GL_TEXTURE_CUBE_MAP, textureId);
	int width, height;
	unsigned char* image = nullptr;

	for (GLuint i = 0; i < faces.size(); i++)
	{
		image = SOIL_load_image(faces[i], &width, &height, 0, SOIL_LOAD_RGB);
		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
		SOIL_free_image_data(image);
	}

	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
	glBindTexture(GL_TEXTURE_CUBE_MAP, 0);

	return textureId;

}

// This function loads a texture from file. Note: texture loading functions like these are usually 
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio). 
// For learning purposes we'll just define it as a utility function.
GLuint loadTexture(GLchar* path, GLboolean alpha /* = GL_FALSE */)
{
	GLuint textureId;
	glGenTextures(1, &textureId);
	glBindTexture(GL_TEXTURE_2D, textureId);


	int width, height;
	unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
	glGenerateMipmap(GL_TEXTURE_2D);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glBindTexture(GL_TEXTURE_2D, 0);
	SOIL_free_image_data(image);

	return textureId;
}

int main()
{
	int glfwState = glfwInit();
	if (glfwState == GLFW_FALSE)
	{
		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, "Sun earth moon", 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, press_key_callback);
	glfwSetCursorPosCallback(window, mouse_move_callback);
	glfwSetScrollCallback(window, scroll_callback);

	//一定要初始化glew,否则,无法创建着色器句柄
	int glewState = glewInit();
	if (glewState != GLEW_OK)
	{
		cout << "GLEW initialize failed,invoke glewInit()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << endl;
		glfwTerminate();
		exit(EXIT_FAILURE);
	}


	const GLubyte* renderer = glGetString(GL_RENDERER);
	const GLubyte* vendor = glGetString(GL_VENDOR);
	const GLubyte* version = glGetString(GL_VERSION);
	const GLubyte* glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);
	GLint major, minor;
	glGetIntegerv(GL_MAJOR_VERSION, &major);
	glGetIntegerv(GL_MINOR_VERSION, &minor);
	printf("GL Vendor : %s\n", vendor);
	printf("GL Renderer : %s\n", renderer);
	printf("GL Version (string) : %s\n", version);
	printf("GL Version (integer) : %d.%d\n", major, minor);
	printf("GLSL Version : %s\n", glslVersion);

	glfwSwapInterval(1);

	init(window);

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


	return 0;
}

vertShader.glsl 顶点着色器

#version 460 core

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

uniform mat4 mv_matrix;
uniform mat4 proj_matrix;

layout(binding = 0) uniform sampler2D samp;

out vec2 tc;

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

fragShader.glsl片元着色器

#version 460 core

in vec2 tc;
out vec4 color;

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

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

源码下载

源码下载地址

视点变换,旋转,加速减速,星空背景 太阳,光晕 各行星纹理 #include #include #include #include #include #include #include #pragma comment(lib, "winmm.lib") #pragma comment(lib,"wininet") // 纹理图像结构 typedef struct { int imgWidth; // 纹理宽度 int imgHeight; // 纹理高度 unsigned char byteCount; // 每个象素对应的字节数,3:24位图,4:alpha通道的24位图 unsigned char *data; // 纹理数据 }TEXTUREIMAGE; // BMP文件头 #pragma pack(2) typedef struct { unsigned short bfType; // 文件类型 unsigned long bfSize; // 文件大小 unsigned short bfReserved1; // 保留位 unsigned short bfReserved2; // 保留位 unsigned long bfOffBits; // 数据偏移位置 }BMPFILEHEADER; #pragma pack() // BMP信息头 typedef struct { unsigned long biSize; // 此结构大小 long biWidth; // 图像宽度 long biHeight; // 图像高度 unsigned short biPlanes; // 调色板数量 unsigned short biBitCount; // 每个象素对应的位数,24:24位图,32:alpha通道的24位图 unsigned long biCompression; // 压缩 unsigned long biSizeImage; // 图像大小 long biXPelsPerMeter;// 横向分辨率 long biYPelsPerMeter;// 纵向分辨率 unsigned long biClrUsed; // 颜色使用数 unsigned long biClrImportant; // 重要颜色数 }BMPINFOHEADER; // 定义窗口的标题、宽度、高度、全屏布尔变量 #define WIN_TITLE "模拟太阳系各星球的转动" const int WIN_WIDTH = 800; const int WIN_HEIGHT = 600; BOOL isFullScreen = FALSE; // 初始不为全屏 #define DEG_TO_RAD 0.017453 float angle=0.0; static GLdouble viewer[]= {0,0,0,0,0}; // 初始化视角 GLUquadricObj *quadric; // 建立二次曲面对象 GLfloat angle_Z; // 星空旋转角度 bool g_bOrbitOn = true; // 控制转动暂停 float g_fSpeedmodifier = 1.0f; // 时间控制 float g_fElpasedTime; double g_dCurrentTime; double g_dLastTime; GLfloat LightAmbient[] = { 1.0f, 1.0f, 1.0f, 0.0f }; // 环境光参数 GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 0.0f }; // 漫射光参数 GLfloat LightPosition[] = { 0.0f, 0.0f, 0.0f, 1.0f }; // 光源的位置 // 纹理图象 TEXTUREIMAGE skyImg; TEXTUREIMAGE sunImg; TEXTUREIMAGE rayImg; TEXTUREIMAGE mercuImg; TEXTUREIMAGE venusImg; TEXTUREIMAGE earthImg; TEXTUREIMAGE marsImg; TEXTUREIMAGE jupiterImg; TEXTUREIMAGE saturnImg; TEXTUREIMAGE uranusImg; TEXTUREIMAGE neptuneImg; TEXTUREIMAGE moonImg; GLuint texture[12]; // 纹理数组 // 星球速度定义 static float fSunSpin = 0.0f; // 太阳自转速度 static float fMercuSpin = 0.0f; // 水星自转速度 static float fMercuOrbit = 0.0f; // 水星公转速度 static float fVenusSpin = 0.0f; // 金星自转速度 static float fVenusOrbit = 0.0f; // 金星公转速度 static float fEarthSpin = 0.0f; // 地球自转速度 static float fEarthOrbit = 0.0f; // 地球公转速度 static float fMarsSpin = 0.0f; // 火星自转速度 static float fMarsOrbit = 0.0f; // 火星公转速度 static float fJupiterSpin = 0.0f; // 木星自转速度 static float fJupiterOrbit = 0.0f; // 木星公转速度 static float fSaturnSpin = 0.0f; // 土星自转速度 static float fSaturnOrbit = 0.0f; // 土星公转速度 static float fUranusSpin = 0.0f; // 天王星自转速度 static float fUranusOrbit = 0.0f; // 天王星公转速度 static float fNeptuneSpin = 0.0f; // 海王星自转速度 static float fNeptuneOrbit = 0.0f; // 海王星公转速度 static float fMoonSpin = 0.0f; // 月亮自转速度 static float fMoonOrbit = 0.0f; // 月亮公转速度 void MakeTexture(TEXTUREIMAGE textureImg, GLuint * texName) //转换为纹理 { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //对齐像素字节函数 glGenTextures(1,texName); //第一个参数指定表明获取多少个连续的纹理标识符 glBindTexture(GL_TEXTURE_2D , *texName); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureImg.imgWidth,textureImg.imgHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, textureImg.data); } // 初始化OpenGL void InitGL(void) { glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //设置黑色背景 glClearDepth(2.0f); // 设置深度缓存 glEnable(GL_DEPTH_TEST); //启动深度测试 glDepthFunc(GL_LEQUAL); //深度小或相等的时候渲染 glShadeModel(GL_SMOOTH); //启动阴影平滑 glEnable(GL_CULL_FACE); //开启剔除操作效果 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //使用质量最好的模式指定颜色和纹理坐标的插值质量 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // 设置环境光 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // 设置漫反射光 glEnable(GL_LIGHTING); // 打开光照 glEnable(GL_LIGHT1); // 打开光源1 // 载入纹理 glEnable(GL_TEXTURE_2D); // 开启2D纹理映射 MakeTexture(skyImg, &texture;[0]); MakeTexture(sunImg, &texture;[1]); MakeTexture(rayImg, &texture;[2]); MakeTexture(mercuImg, &texture;[3]); MakeTexture(venusImg, &texture;[4]); MakeTexture(earthImg, &texture;[5]); MakeTexture(marsImg, &texture;[6]); MakeTexture(jupiterImg, &texture;[7]); MakeTexture(saturnImg, &texture;[8]); MakeTexture(uranusImg, &texture;[9]); MakeTexture(neptuneImg, &texture;[10]); MakeTexture(moonImg, &texture;[11]); quadric = gluNewQuadric(); // 建立一个曲面对象指针 gluQuadricTexture(quadric, GLU_TRUE); // 建立纹理坐标 gluQuadricDrawStyle(quadric, GLU_FILL); // 面填充 } void Display(void) { glLoadIdentity(); // 设置观察点的位置和观察的方向 gluLookAt(viewer[0],viewer[1],viewer[2],viewer[3],viewer[4],-5,0,1,0); //摄像机x,摄像机y,摄像机z, 目标点x,目标点y,目标点z, 摄像机顶朝向x,摄像机顶朝向y,摄像机顶朝向z // 获得系统时间使太阳系有动态效果 g_dCurrentTime = timeGetTime(); g_fElpasedTime = (float)((g_dCurrentTime - g_dLastTime) * 0.0005); g_dLastTime = g_dCurrentTime; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode( GL_MODELVIEW ); //指定GL_MODELVIEW是下一个矩阵操作的目标 glTranslatef(0.0f, 0.0f, -5.0f); // 将坐标系移入屏幕5.0f glRotatef(10, 1.0f ,0.0f, 0.0f); // 将坐标系绕x轴旋转10度 glEnable(GL_LIGHT0); // 打开光源0 /**********************************绘制背景星空********************************************/ glPushMatrix (); // 当前模型矩阵入栈 glTranslatef(-10.0f, 3.0f, 0.0f); glRotatef(angle_Z, 0.0f, 0.0f, 1.0f); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture[0]); // 星空纹理 glBegin(GL_QUADS); glNormal3f( 0.0f, 0.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-50.0f, -50.0f, -50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f( 50.0f, -50.0f, -50.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f( 50.0f, 50.0f, -50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f(-50.0f, 50.0f, -50.0f); glEnd(); glBegin(GL_QUADS); glNormal3f( 0.0f, 0.0f, -1.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f(-50.0f, -50.0f, 50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f( 50.0f, -50.0f, 50.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 50.0f, 50.0f, 50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f(-50.0f, 50.0f, 50.0f); glEnd(); glBegin(GL_QUADS); glNormal3f( 0.0f, 1.0f, 0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-50.0f, -50.0f, -50.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f( 50.0f, -50.0f, 50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f( 50.0f, -50.0f, -50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f(-50.0f, -50.0f, 50.0f); glEnd(); glBegin(GL_QUADS); glNormal3f( 0.0f, -1.0f, 0.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f(-50.0f, 50.0f, -50.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 50.0f, 50.0f, 50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f( 50.0f, 50.0f, -50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f(-50.0f, 50.0f, 50.0f); glEnd(); glBegin(GL_QUADS); glNormal3f( 1.0f, 0.0f, 0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-50.0f, -50.0f, -50.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f(-50.0f, 50.0f, 50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f(-50.0f, -50.0f, 50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f(-50.0f, 50.0f, -50.0f); glEnd(); glBegin(GL_QUADS); glNormal3f( -1.0f, 0.0f, 0.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f(50.0f, -50.0f, -50.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(50.0f, 50.0f, 50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f(50.0f, -50.0f, 50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f(50.0f, 50.0f, -50.0f); glEnd(); glPopMatrix (); // 当前模型矩阵出栈 /**********************************绘制太阳************************************************/ glBindTexture(GL_TEXTURE_2D, texture[2]); // 光晕纹理 glEnable(GL_BLEND); // 开启混合 glDisable(GL_DEPTH_TEST); // 关闭深度测试 // 绘制太阳光晕 glDisable(GL_LIGHTING); // 关闭光照 glBlendFunc(GL_SRC_ALPHA,GL_ONE); // 半透明混合函数 glColor4f(1.0f, 0.5f, 0.0f, 0.5f); // 设置RGBA值 glBegin(GL_QUADS); glNormal3f( 0.0f, 0.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f); glEnd(); glDisable(GL_BLEND); // 关闭混合 glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); // 开启光照 glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); // 设置光源1位置 glBindTexture(GL_TEXTURE_2D, texture[1]); // 太阳纹理 // 将坐标系绕Y轴旋转fSunSpin角度,控制太阳自转 glRotatef(fSunSpin,0.0,1.0,0.0); gluSphere(quadric, 0.3f, 32, 32); // 绘制太阳球体 /**********************************绘制水星************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fMercuOrbit角度,控制水星公转 glRotatef(fMercuOrbit, 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(0.5f, 0.0f, 0.0f); // 将坐标系右移0.5f glBindTexture(GL_TEXTURE_2D, texture[3]); // 水星纹理 // 将坐标系绕Z轴旋转fMercuSpin角度 控制水星自转 glRotatef(fMercuSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.04f, 32, 32); // 水星球体 glPopMatrix (); // 当前模型视图矩阵出栈 // 绘制轨道 glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(0.5f*sin(DEG_TO_RAD*angle),0,0.5f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制金星************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fVenusOrbit角度,控制金星公转 glRotatef(fVenusOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);// 将坐标系绕X轴旋转-90度 glTranslatef(0.8f, 0.0f, 0.0f); // 将坐标系右移0.8f glBindTexture(GL_TEXTURE_2D, texture[4]); // 金星纹理 // 将坐标系绕Z轴旋转fVenusSpin角度,控制金星自转 glRotatef(fVenusSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.06f, 32, 32); // 金星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(0.8f*sin(DEG_TO_RAD*angle),0,0.8f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制地球************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fEarthOrbit角度,控制地球公转 glRotatef(fEarthOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);// 将坐标系绕X轴旋转-90度 glTranslatef(1.1f, 0.0f, 0.0f); // 将坐标系右移1.1f glBindTexture(GL_TEXTURE_2D, texture[5]); // 地球纹理 // 将坐标系绕Z轴旋转fEarthSpin角度,控制地球自转 glRotatef(fEarthSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.08f, 32, 32); // 地球球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(1.1f*sin(DEG_TO_RAD*angle),0,1.1f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制火星************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fMarsOrbit角度,控制火星公转 glRotatef(fMarsOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(1.4f, 0.0f, 0.0f); // 将坐标系右移1.4f glBindTexture(GL_TEXTURE_2D, texture[6]); // 火星纹理 // 将坐标系绕Z轴旋转fMarsSpin角度,控制火星自转 glRotatef(fMarsSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.04f, 32, 32); // 火星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(1.4f*sin(DEG_TO_RAD*angle),0,1.4f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制木星************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fJupiterOrbit角度,控制木星公转 glRotatef(fJupiterOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(1.7f, 0.0f, 0.0f); // 将坐标系右移1.7f glBindTexture(GL_TEXTURE_2D, texture[7]); // 木星纹理 // 将坐标系绕Z轴旋转fJupiterSpin角度,控制木星自转 glRotatef(fJupiterSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.13f, 32, 32); // 木星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(1.7f*sin(DEG_TO_RAD*angle),0,1.7f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制土星************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fSaturnOrbit角度,控制土星公转 glRotatef(fSaturnOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(1.9f, 0.0f, 0.0f); // 将坐标系右移1.9f glBindTexture(GL_TEXTURE_2D, texture[8]); // 土星纹理 // 将坐标系绕Z轴旋转fSaturnSpin角度,控制土星自转 glRotatef(fSaturnSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.1f, 32, 32); // 土星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(1.9f*sin(DEG_TO_RAD*angle),0,1.9f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制天王星**********************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fUranusOrbit角度,控制天王星公转 glRotatef(fUranusOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(2.1f, 0.0f, 0.0f); // 将坐标系右移2.1f glBindTexture(GL_TEXTURE_2D, texture[9]); // 天王星纹理 // 将坐标系绕Z轴旋转fUranusSpin角度,控制天王星自转 glRotatef(fUranusSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.1f, 32, 32); // 天王星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(2.1f*sin(DEG_TO_RAD*angle),0,2.1f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制海王星**********************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fNeptuneOrbit角度,控制海王星公转 glRotatef(fNeptuneOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(2.3f, 0.0f, 0.0f); // 将坐标系右移2.3f glBindTexture(GL_TEXTURE_2D, texture[10]); // 海王星纹理 // 将坐标系绕Z轴旋转fNeptuneSpin角度,控制海王星自转 glRotatef(fNeptuneSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.08f, 32, 32); // 海王星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(2.3f*sin(DEG_TO_RAD*angle),0,2.3f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制月亮************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // glBindTexture(GL_TEXTURE_2D, texture[11]); // 月亮纹理 glPushMatrix (); // 将坐标系绕Y轴旋转fEarthOrbit角度,控制月亮跟随地球 glRotatef(fEarthOrbit , 0.0f, 1.0f, 0.0f); glTranslatef(1.1f, 0.0f, 0.0f); // 将坐标系右移1.1f // 将坐标系绕Y轴旋转fMoonOrbit角度,控制月亮公转 glRotatef(fMoonOrbit , 0.0f, 1.0f, 0.0f); glTranslatef(0.15f, 0.0f, 0.0f); // 将坐标系绕Y轴旋转fMoonSpin角度,控制月亮自转 glBindTexture(GL_TEXTURE_2D, texture[11]); glRotatef(fMoonSpin , 0.0f, 1.0f, 0.0f); gluSphere(quadric, 0.02, 32, 32); // 月亮球体 glPopMatrix (); // 控制各星球转动的速度 if( g_bOrbitOn == true ) { fSunSpin -= g_fSpeedmodifier * (g_fElpasedTime * 10.0f); fMercuSpin -= g_fSpeedmodifier * (g_fElpasedTime * 15.0f); fMercuOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 40.0f); fVenusSpin -= g_fSpeedmodifier * (g_fElpasedTime * 10.0f); fVenusOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 30.0f); fEarthSpin -= g_fSpeedmodifier * (g_fElpasedTime * 100.0f); fEarthOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 20.0f); fMarsSpin -= g_fSpeedmodifier * (g_fElpasedTime * 30.0f); fMarsOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 50.0f); fJupiterSpin -= g_fSpeedmodifier * (g_fElpasedTime * 90.0f); fJupiterOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 35.0f); fSaturnSpin -= g_fSpeedmodifier * (g_fElpasedTime * 90.0f); fSaturnOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 25.0f); fUranusSpin -= g_fSpeedmodifier * (g_fElpasedTime * 70.0f); fUranusOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 15.0f); fNeptuneSpin -= g_fSpeedmodifier * (g_fElpasedTime * 40.0f); fNeptuneOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 5.0f); fMoonSpin -= g_fSpeedmodifier * (g_fElpasedTime * 50.0f); fMoonOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 200.0f); } angle_Z += 0.01f; // 星空旋转 glutSwapBuffers(); // 交换双缓存 glFlush(); } void Reshape(int width, int height) { if (height==0) height=1; // 改变窗口 glViewport(0,0,width,height); // 设置视口 // 设置投影矩阵 glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(viewer[0],viewer[1],viewer[2],viewer[3],viewer[4],-5,0,1,0); } void keyboard(unsigned char key, int x, int y) { switch(key) { case 'r': case 'R': // 视点上下左右移动 if(viewer[0]=-6.0) viewer[0]-=0.5; break; case 'u': case 'U': if(viewer[1]=-6.0) viewer[1]-=0.1; break; case'+': case '=': // 加速,减速,暂停 g_fSpeedmodifier+=1.0f; glutPostRedisplay(); break; case ' ': g_bOrbitOn = !g_bOrbitOn; glutPostRedisplay(); break; case'-': //按'-'减小运行速度 g_fSpeedmodifier-=1.0f; glutPostRedisplay(); break; case VK_ESCAPE: // 按ESC键时退出 exit(0); break; default: break; } } void special_keys(int s_keys, int x, int y) { switch(s_keys) { case GLUT_KEY_F1: // 按F1键时切换窗口/全屏模式 if(isFullScreen) { glutReshapeWindow(WIN_WIDTH, WIN_HEIGHT); glutPositionWindow(30, 30); isFullScreen = FALSE; } else { glutFullScreen(); isFullScreen = TRUE; } break; case GLUT_KEY_RIGHT: // 视角上下左右旋转 if(viewer[3]=-3.0) viewer[3]-=0.1; break; case GLUT_KEY_UP: if(viewer[4]=-4.5) viewer[4]-=0.1; break; default: break; } } void mouse(int btn, int state, int x, int y) // 远近视角 { if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) viewer[2]+=0.3; if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN&&viewer;[2]>=-3.9) viewer[2]-=0.3; } void LoadBmp(char *filename, TEXTUREIMAGE *textureImg) // 载入图片 { int i, j; FILE *file; BMPFILEHEADER bmpFile; BMPINFOHEADER bmpInfo; int pixel_size; // 初始化纹理数据 textureImg->imgWidth = 0; textureImg->imgHeight = 0; if (textureImg->data != NULL) { delete []textureImg->data; } // 打开文件 file = fopen(filename, "rb"); if (file == NULL) { return; } // 获取文件头 rewind(file); fread(&bmpFile;, sizeof(BMPFILEHEADER), 1, file); fread(&bmpInfo;, sizeof(BMPINFOHEADER), 1, file); // 验证文件类型 if (bmpFile.bfType != 0x4D42) { return; } // 获取图像色彩数 pixel_size = bmpInfo.biBitCount >> 3; // 读取文件数据 textureImg->data = new unsigned char[bmpInfo.biWidth * bmpInfo.biHeight * pixel_size]; for(i = 0 ; i < bmpInfo.biHeight; i++) { fseek(file, bmpFile.bfOffBits + (bmpInfo.biHeight - i - 1) * bmpInfo.biWidth * pixel_size, SEEK_SET); for (j = 0; j data + (i * bmpInfo.biWidth + j) * pixel_size + 2, sizeof(unsigned char), 1, file); // 绿色分量 fread(textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 1, sizeof(unsigned char), 1, file); // 蓝色分量 fread(textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 0, sizeof(unsigned char), 1, file); // Alpha分量 if (pixel_size == 4) { fread(textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 3, sizeof(unsigned char), 1, file); } } } // 记录图像相关参数 textureImg->imgWidth = bmpInfo.biWidth; textureImg->imgHeight = bmpInfo.biHeight; textureImg->byteCount = pixel_size; fclose(file); } // 程序主函数 void main(int argc, char** argv) { //读图片 LoadBmp("Picture//Sky.bmp" , &skyImg;); LoadBmp("Picture//Sun.bmp" , &sunImg;); LoadBmp("Picture//Ray.bmp" , &rayImg;); LoadBmp("Picture//Mercu.bmp" , &mercuImg;); LoadBmp("Picture//Venus.bmp" , &venusImg;); //金星 LoadBmp("Picture//Earth.bmp" , &earthImg;); LoadBmp("Picture//Mars.bmp" , &marsImg;); //火星 LoadBmp("Picture//Jupiter.bmp" , &jupiterImg;); //木星 LoadBmp("Picture//Saturn.bmp" , &saturnImg;); //土星 LoadBmp("Picture//Uranus.bmp" , &uranusImg;); //天王星 LoadBmp("Picture//Neptune.bmp" , &neptuneImg;); //海王星 LoadBmp("Picture//Moon.bmp" , &moonImg;); glutInit(&argc;, argv); // 初始化GLUT库 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); // 初始化显示模式 glutInitWindowSize(WIN_WIDTH, WIN_HEIGHT); // 初始化窗口大小 glutInitWindowPosition(20,20); // 初始化窗口位置 GLuint window = glutCreateWindow(WIN_TITLE); // 建立窗口 InitGL(); // 初始化OpenGL glutDisplayFunc(Display); glutReshapeFunc(Reshape); glutKeyboardFunc(keyboard); glutSpecialFunc(special_keys); glutMouseFunc(mouse); glutIdleFunc(Display); // 设置窗口空闲时的处理函数 glutMainLoop(); // 进入事件处理循环 }
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值