OpenGL

cpp 复制代码
#include <iostream>
#include <fstream>
#include <string>
#include <random>
#include <cmath>

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <soil2/SOIL2.h>

#include "utils.h"
#include "geometry.h"
#include "noise.h"

#define SPEED 0.2f
#define ANGLE 0.03f

using namespace std;

GLuint rendering_program;
GLuint snow_program;
GLuint sky_program;

GLuint texture_id;

GLuint global_amb_loc;
GLuint dirlight_amb_loc;
GLuint dirlight_dif_loc;
GLuint dirlight_spe_loc;
GLuint dirlight_dir_loc;

int HEIGHT = 724, WIDTH = 1024;
float aspect = (float)WIDTH / (float)HEIGHT;

glm::vec4 GlobalAmbient = { 0.2f, 0.2f, 0.2f, 1.0f };		//全局环境光
glm::vec4 DirLightAmbient = { 0.1f, 0.1f, 0.1f, 1.0f };		//定向光:环境特征
glm::vec4 DirLightDiffuse = { 0.70f, 0.70f, 0.70f, 1.0f };	//定向光:漫反射
glm::vec4 DirLightSpecular = { 0.70f, 0.70f, 0.70f, 1.0f };
glm::vec3 DirLightDirection = { 0.0f, -0.866f, -0.5f };
float DirLightAngle = PI / 2.0f;

Camera camera;
Vertex_Manager vm;
Object* square;
Object* snow;
Object* tetrahedron;
Object* icosahedron;
Object* cube;
Object* cone;
Object* sphere;
Object* water_droplet;
Object* surface;

void init(GLFWwindow* window) {
	srand((unsigned int)time(NULL));
	camera.vmat = glm::mat4(1.0f);
	camera.tmat = glm::mat4(1.0f);
	camera.rmat = glm::mat4(1.0f);
	camera.pmat = glm::perspective(1.3f, aspect, 0.2f, 500.0f);
	rendering_program = CreateShaderProgram("vert_shader.glsl", "frag_shader.glsl");
	snow_program = CreateShaderProgram("snow_vert.glsl", "snow_frag.glsl");
	sky_program = CreateShaderProgram("sky_vert.glsl", "sky_frag.glsl");
	texture_id = CreateNoisyTexture256(glm::vec4(0.0f, 0.5f, 1.0f, 0.0f), glm::vec4(1.0f, 1.0f, 1.0f, 0.0f), MD);
	glGenVertexArrays(numVAOs, vm.vao);
	glBindVertexArray(vm.vao[0]);
	glGenBuffers(numVBOs, vm.vbo);
	square = CreateSquare(&vm, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 1.0f, 0.0f, 0.0f));
	snow = CreateSnow(&vm, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec4(0.8f, 0.8f, 0.8f, 1.0f));
	tetrahedron = CreateTetrahedron(&vm, glm::vec3(6.0f, 2.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 0.0f));
	icosahedron = CreateIcosahedron(&vm, glm::vec3(6.0f, 4.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 0.0f));
	cube = CreateCube(&vm, glm::vec3(6.0f, 6.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 0.0f));
	cone = CreateCone(&vm, glm::vec3(6.0f, 8.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 10.0f), PI / 6.0f);
	sphere = CreateSphere(&vm, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f));
	water_droplet = CreateWaterDroplet(&vm, glm::vec3(6.0f, 12.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 0.0f));
	glm::vec3 p[4][4] = {
		glm::vec3(-1.0f,0.0f, -1.0f), glm::vec3(-1.0f, 0.0f, -0.0f), glm::vec3(-1.0f, 0.0f, 1.0f), glm::vec3(-1.0f, 1.0f, 2.0f),
		glm::vec3(0.0f, 1.0f, -1.0f), glm::vec3(0.0f, 0.0f, -0.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec3(0.0f, 2.0f, 2.0f),
		glm::vec3(1.0f, -1.0f, -1.0f), glm::vec3(1.5f, 0.0f, -0.0f), glm::vec3(1.5f, 1.0f, 1.0f), glm::vec3(1.0f, 3.0f, 2.0f),
		glm::vec3(2.5f, 0.0f, -1.0f), glm::vec3(2.5f, 0.0f, -0.0f), glm::vec3(2.5f, 0.0f, 1.0f), glm::vec3(2.0f, 1.0f, 2.0f)
	};
	surface = CreateSurface(&vm, glm::vec3(0.0f, 3.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), p);
}
void MoveCamera(GLFWwindow* window) {
	if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
		camera.position[0] -= (float)sin(camera.theta) * SPEED;
		camera.position[2] -= (float)cos(camera.theta) * SPEED;
	}
	if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
		camera.position[0] += (float)sin(camera.theta) * SPEED;
		camera.position[2] += (float)cos(camera.theta) * SPEED;
	}
	if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
		camera.position[0] -= (float)cos(camera.theta) * SPEED;
		camera.position[2] += (float)sin(camera.theta) * SPEED;
	}
	if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
		camera.position[0] += (float)cos(camera.theta) * SPEED;
		camera.position[2] -= (float)sin(camera.theta) * SPEED;
	}
	if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) {
		camera.position[1] += SPEED;
	}
	if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS) {
		camera.position[1] -= SPEED;
	}
	if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) {
		if (camera.phi < PI / 2.0) {
			camera.phi += ANGLE;
		}
	}
	if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) {
		if (camera.phi > -PI / 2.0) {
			camera.phi -= ANGLE;
		}
	}
	if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) {
		camera.theta += ANGLE;
	}
	if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) {
		camera.theta -= ANGLE;
	}
	if (glfwGetKey(window, GLFW_KEY_T) == GLFW_PRESS) {
		DirLightAngle += ANGLE;
		DirLightDirection = { -cos(DirLightAngle), -0.866f * sin(DirLightAngle), -0.5f * sin(DirLightAngle)};
	}
	camera.tmat = glm::translate(glm::mat4(1.0f), -camera.position);
	camera.rmat = {
		{ cos(camera.theta)  , sin(camera.phi) * sin(camera.theta), cos(camera.phi) * sin(camera.theta), 0.0f },
		{ 0.0f				 , cos(camera.phi)					 , -sin(camera.phi)				   , 0.0f },
		{ -sin(camera.theta) , sin(camera.phi) * cos(camera.theta), cos(camera.phi) * cos(camera.theta), 0.0f },
		{ 0.0f				 , 0.0f								 , 0.0f								   , 1.0f }
	};
	camera.vmat = camera.rmat * camera.tmat;
}
void WindowReshapeCallback(GLFWwindow* window, int new_width, int new_height) {
	WIDTH = new_width;
	HEIGHT = new_height;
	aspect = (float)WIDTH / (float)HEIGHT;
	camera.pmat = glm::perspective(1.3f, aspect, 0.2f, 500.0f);
	glViewport(0, 0, WIDTH, HEIGHT);
}
void InstallLight(GLuint program) {
	global_amb_loc = glGetUniformLocation(program, "GlobalAmbient");
	dirlight_amb_loc = glGetUniformLocation(program, "DirLightAmbient");
	dirlight_dif_loc = glGetUniformLocation(program, "DirLightDiffuse");
	dirlight_spe_loc = glGetUniformLocation(program, "DirLightSpecular");
	dirlight_dir_loc = glGetUniformLocation(program, "DirLightDirection");
	glProgramUniform4fv(program, global_amb_loc, 1, glm::value_ptr(GlobalAmbient));
	glProgramUniform4fv(program, dirlight_amb_loc, 1, glm::value_ptr(DirLightAmbient));
	glProgramUniform4fv(program, dirlight_dif_loc, 1, glm::value_ptr(DirLightDiffuse));
	glProgramUniform4fv(program, dirlight_spe_loc, 1, glm::value_ptr(DirLightSpecular));
	glProgramUniform3fv(program, dirlight_dir_loc, 1, glm::value_ptr(DirLightDirection));
}
void display(GLFWwindow* window, double current_time) {
	glClear(GL_DEPTH_BUFFER_BIT);
	glClear(GL_COLOR_BUFFER_BIT);

	glDisable(GL_CULL_FACE);
	glDisable(GL_DEPTH_TEST);

	glUseProgram(sky_program);
	camera.mvloc = glGetUniformLocation(sky_program, "mvmat");
	camera.ploc = glGetUniformLocation(sky_program, "pmat");
	camera.mvmat = camera.vmat * glm::translate(glm::mat4(1.0f), camera.position);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_3D, texture_id);
	glUniformMatrix4fv(camera.mvloc, 1, GL_FALSE, glm::value_ptr(camera.mvmat));
	glUniformMatrix4fv(camera.ploc, 1, GL_FALSE, glm::value_ptr(camera.pmat));
	glBindBuffer(GL_ARRAY_BUFFER, vm.vbo[sphere->vbo_index[0]]);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);
	glDrawArrays(GL_TRIANGLES, 0, sphere->size / 3);


	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

	glUseProgram(snow_program);
	camera.mvloc = glGetUniformLocation(snow_program, "mvmat");
	camera.ploc = glGetUniformLocation(snow_program, "pmat");
	camera.cloc = glGetUniformLocation(snow_program, "texture_color");
	camera.tloc = glGetUniformLocation(snow_program, "current_time");
	camera.mvmat = camera.vmat;
	glUniformMatrix4fv(camera.mvloc, 1, GL_FALSE, glm::value_ptr(camera.mvmat));
	glUniformMatrix4fv(camera.ploc, 1, GL_FALSE, glm::value_ptr(camera.pmat));
	glUniform4fv(camera.cloc, 1, glm::value_ptr(snow->texture_color));
	glUniform1f(camera.tloc, (GLfloat)current_time);
	glBindBuffer(GL_ARRAY_BUFFER, vm.vbo[snow->vbo_index[0]]);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);
	glDrawArraysInstanced(GL_TRIANGLES, 0, snow->size / 3, 100000);

	glUseProgram(rendering_program);
	InstallLight(rendering_program);
	camera.mvloc = glGetUniformLocation(rendering_program, "mvmat");
	camera.ploc = glGetUniformLocation(rendering_program, "pmat");
	camera.nloc = glGetUniformLocation(rendering_program, "nmat");
	camera.cloc = glGetUniformLocation(rendering_program, "texture_color");
	
	for (int x = -32; x < 32; x++) {
		for (int y = -32; y < 32; y++) {
			square->position = glm::vec3(float(x) + 0.5f, 0.0f, float(y) + 0.5f);
			square->texture_color = glm::vec4(0.0f, float((x + y) & 1), float(!bool((x + y) & 1)), 0.0f);
			DrawObject(&camera, &vm, square);
		}
	}
	DrawObject(&camera, &vm, cone);
	DrawObject(&camera, &vm, surface);
	glEnable(GL_CULL_FACE);
	DrawObject(&camera, &vm, tetrahedron);
	DrawObject(&camera, &vm, icosahedron);
	DrawObject(&camera, &vm, water_droplet);
}
int main() {
	if (!glfwInit()) { exit(EXIT_FAILURE); }
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "HelloWorld", NULL, NULL);
	glfwMakeContextCurrent(window);
	if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }
	glfwSwapInterval(1);
	glfwSetWindowSizeCallback(window, WindowReshapeCallback);

	init(window);

	double pre = glfwGetTime();
	while (!glfwWindowShouldClose(window)) {
		MoveCamera(window);
		display(window, pre);
		glfwSwapBuffers(window);
		glfwPollEvents();
		while (glfwGetTime() - pre <= 0.02);
		pre = glfwGetTime();
	}

	DestroyObject(square);
	DestroyObject(snow);
	DestroyObject(tetrahedron);
	DestroyObject(icosahedron);
	DestroyObject(cube);
	DestroyObject(cone);
	DestroyObject(sphere);
	DestroyObject(water_droplet);
	DestroyObject(surface);

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

utils.h

cpp 复制代码
#pragma once

#include <iostream>
#include <fstream>
#include <string>
#include <random>
#include <cmath>

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <soil2/SOIL2.h>

using namespace std;

string ReadShaderSource(const char* file_path) {
	string content;
	string line = "";
	ifstream file_stream(file_path, ios::in);
	while (!file_stream.eof()) {
		getline(file_stream, line);
		content.append(line + "\n");
	}
	file_stream.close();
	return content;
}
void PrintShaderLog(GLuint shader) {
	int len = 0;
	int ch_writtn = 0;
	char* log;
	glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
	if (len > 0) {
		log = (char*)malloc(len);
		glGetShaderInfoLog(shader, len, &ch_writtn, log);
		cout << "Shader Info Log:" << log << endl;
		free(log);
	}
}
void PrintProgramLog(GLuint program) {
	int len = 0;
	int ch_writtn = 0;
	char* log;
	glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
	if (len > 0) {
		log = (char*)malloc(len);
		glGetProgramInfoLog(program, len, &ch_writtn, log);
		cout << "Program Info Log:" << log << endl;
		free(log);
	}
}
bool CheckOpenGLError() {
	bool found_error = false;
	int glerr = glGetError();
	while (glerr != GL_NO_ERROR) {
		cout << "GL ERROR:" << glerr << endl;
		found_error = true;
		glerr = glGetError();
	}
	return found_error;
}
GLuint CreateShaderProgram(const char* vert_shader_file, const char* frag_shader_file) {
	GLuint vshader = glCreateShader(GL_VERTEX_SHADER);
	GLuint fshader = glCreateShader(GL_FRAGMENT_SHADER);
	GLint vert_compiled;
	GLint frag_compiled;
	GLint linked;
	string vert_shader_string = ReadShaderSource(vert_shader_file);
	string frag_shader_string = ReadShaderSource(frag_shader_file);
	const char* vert_shader_source = vert_shader_string.c_str();
	const char* frag_shader_source = frag_shader_string.c_str();
	glShaderSource(vshader, 1, &vert_shader_source, NULL);
	glShaderSource(fshader, 1, &frag_shader_source, NULL);
	cout << "create shader program" << endl;
	glCompileShader(vshader);
	CheckOpenGLError();
	glGetShaderiv(vshader, GL_COMPILE_STATUS, &vert_compiled);
	if (vert_compiled != 1) {
		cout << "vertex compilation failed" << endl;
		PrintShaderLog(vshader);
	}
	glCompileShader(fshader);
	CheckOpenGLError();
	glGetShaderiv(fshader, GL_COMPILE_STATUS, &frag_compiled);
	if (frag_compiled != 1) {
		cout << "fragment compilation failed" << endl;
		PrintShaderLog(fshader);
	}
	GLuint program = glCreateProgram();
	glAttachShader(program, vshader);
	glAttachShader(program, fshader);
	glLinkProgram(program);
	CheckOpenGLError();
	glGetProgramiv(program, GL_LINK_STATUS, &linked);
	if (linked != 1) {
		cout << "linking failed" << endl;
		PrintProgramLog(program);
	}
	return program;
}
GLuint LoadTexture(const char* ImagePath) {
	GLuint textureID;
	textureID = SOIL_load_OGL_texture(ImagePath, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
	if (textureID == 0) cout << "could not find texture file:" << ImagePath << endl;
	return textureID;
}

geometry.h

cpp 复制代码
#pragma once

#include <iostream>
#include <fstream>
#include <string>
#include <random>
#include <cmath>

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <soil2/SOIL2.h>

#define numVAOs 1
#define numVBOs 128
#ifndef PI
#define PI 3.14159f
#endif

using namespace std;

struct Camera {
	float theta, phi;
	glm::vec3 position;
	glm::mat4 tmat;					//平移
	glm::mat4 rmat;					//旋转
	glm::mat4 vmat;					//t_mat * r_mat
	glm::mat4 pmat;					//透视
	glm::mat4 mvmat;
	glm::mat4 invmat;				//mv矩阵的逆
	GLuint mvloc;
	GLuint ploc;					//透视
	GLuint nloc;					//逆矩阵
	GLuint cloc;					//颜色
	GLuint tloc;					//时间
};
struct Vertex_Manager {
	GLuint vao[numVAOs]{};
	GLuint vbo[numVBOs]{};
	GLuint vbo_count = 0;
};
struct Object {
	GLuint size;					//顶点个数
	GLuint vbo_index[2];
	glm::vec3 position;
	glm::vec4 texture_color;
	float* vertex_positions;
	float* vertex_normals;
};
Object* CreateObject(Vertex_Manager* vm, GLuint size, glm::vec3 pos, glm::vec4 color, float* v_pos, float* v_nor) {
	Object* obj = new Object;
	obj->size = size;
	obj->position = pos;
	obj->texture_color = color;
	obj->vbo_index[0] = vm->vbo_count++;
	obj->vbo_index[1] = vm->vbo_count++;
	obj->vertex_positions = new float[size];
	obj->vertex_normals = new float[size];
	for (GLuint i = 0; i < size; i++) {
		obj->vertex_positions[i] = v_pos[i];
		obj->vertex_normals[i] = v_nor[i];
	}
	glBindBuffer(GL_ARRAY_BUFFER, vm->vbo[obj->vbo_index[0]]);
	glBufferData(GL_ARRAY_BUFFER, size * sizeof(float), obj->vertex_positions, GL_STATIC_DRAW);
	glBindBuffer(GL_ARRAY_BUFFER, vm->vbo[obj->vbo_index[1]]);
	glBufferData(GL_ARRAY_BUFFER, size * sizeof(float), obj->vertex_normals, GL_STATIC_DRAW);
	return obj;
}
Object* CreateSquare(Vertex_Manager* vm, glm::vec3 pos, glm::vec4 color) {
	float v_pos[18] = {
		0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
		1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f
	};
	float v_nor[18] = {
		0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
		0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f
	};
	Object* obj = CreateObject(vm, 18, pos, color, v_pos, v_nor);
	return obj;
}
Object* CreateSnow(Vertex_Manager* vm, glm::vec3 pos, glm::vec4 color) {
	float v_pos[18] = {
		-0.1732f, -0.1f, 0.0f, 0.1732f, -0.1f, 0.0f, 0.0f, 0.2f, 0.0f,
		-0.1732f, 0.1f, 0.0f, 0.1732f, 0.1f, 0.0f, 0.0f, -0.2f, 0.0f
	};
	float v_nor[18] = {
		0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
		0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f
	};
	Object* obj = CreateObject(vm, 18, pos, color, v_pos, v_nor);
	return obj;
}
Object* CreateTetrahedron(Vertex_Manager* vm, glm::vec3 pos, glm::vec4 color) {
	float v_pos[36] = {
		0.0f, -0.408f, 1.155f, -1.0f, -0.408f, -0.577f, 1.0f, -0.408f, -0.577f,
		0.0f, -0.408f, 1.155f, 0.0f, 1.225f, 0.0f, -1.0f, -0.408f, -0.577f,
		0.0f, -0.408f, 1.155f, 1.0f, -0.408f, -0.577f, 0.0f, 1.225f, 0.0f,
		-1.0f, -0.408f, -0.577f, 0.0f, 1.225f, 0.0f, 1.0f, -0.408f, -0.577f
	};
	float v_nor[36] = {
		0.0f, -1.225f, -0.0f, 0.0f, -1.225f, 0.0f, 0.0f, -1.225f, 0.0f,
		-1.0f, 0.408f, 0.577f, -1.0f, 0.408f, 0.577f, -1.0f, 0.408f, 0.577f,
		1.0f, 0.408f, 0.577f, 1.0f, 0.408f, 0.577f, 1.0f, 0.408f, 0.577f,
		0.0f, 0.408f, -1.155f, 0.0f, 0.408f, -1.155f, 0.0f, 0.408f, -1.155f
	};
	Object* obj = CreateObject(vm, 36, pos, color, v_pos, v_nor);
	return obj;
}
Object* CreateIcosahedron(Vertex_Manager* vm, glm::vec3 pos, glm::vec4 color) {
	float v_pos[180] = {
		-0.618f, 1.0f, 0.0f, 0.618f, 1.0f, 0.0f, 0.0f, 0.618f, -1.0f,
		0.618f, -1.0f, 0.0f, -0.618f, -1.0f, 0.0f, 0.0f, -0.618f, -1.0f,
		0.0f, 0.618f, -1.0f, -1.0f, 0.0f, -0.618f, -0.618f, 1.0f, 0.0f,
		-1.0f, 0.0f, -0.618f, 0.0f, -0.618f, -1.0f, -0.618f, -1.0f, 0.0f,
		0.618f, 1.0f, 0.0f, 1.0f, 0.0f, -0.618f, 0.0f, 0.618f, -1.0f,
		1.0f, 0.0f, -0.618f, 0.618f, -1.0f, 0.0f, 0.0f, -0.618f, -1.0f,
		-1.0f, 0.0f, -0.618f, 0.0f, 0.618f, -1.0f, 0.0f, -0.618f, -1.0f,
		0.0f, -0.618f, -1.0f, 0.0f, 0.618f, -1.0f, 1.0f, 0.0f, -0.618f,
		0.618f, 1.0f, 0.0f, -0.618f, 1.0f, 0.0f, 0.0f, 0.618f, 1.0f,
		-0.618f, -1.0f, 0.0f, 0.618f, -1.0f, 0.0f, 0.0f, -0.618f, 1.0f,
		-1.0f, 0.0f, 0.618f, 0.0f, 0.618f, 1.0f, -0.618f, 1.0f, 0.0f,
		-1.0f, 0.0f, 0.618f, -0.618f, -1.0f, 0.0f, 0.0f, -0.618f, 1.0f,
		0.618f, 1.0f, 0.0f, 0.0f, 0.618f, 1.0f, 1.0f, 0.0f, 0.618f,
		0.0f, -0.618f, 1.0f, 0.618f, -1.0f, 0.0f, 1.0f, 0.0f, 0.618f,
		0.0f, -0.618f, 1.0f, 0.0f, 0.618f, 1.0f, -1.0f, 0.0f, 0.618f,
		0.0f, 0.618f, 1.0f, 0.0f, -0.618f, 1.0f, 1.0f, 0.0f, 0.618f,
		-1.0f, 0.0f, 0.618f, -0.618f, 1.0f, 0.0f, -1.0f, 0.0f, -0.618f,
		-1.0f, 0.0f, 0.618f, -1.0f, 0.0f, -0.618f, -0.618f, -1.0f, 0.0f,
		1.0f, 0.0f, 0.618f, 1.0f, 0.0f, -0.618f, 0.618f, 1.0f, 0.0f,
		1.0f, 0.0f, -0.618f, 1.0f, 0.0f, 0.618f, 0.618f, -1.0f, 0.0f
	};
	float v_nor[180] = {
		0.0f, 2.618f, -1.0f, 0.0f, 2.618f, -1.0f, 0.0f, 2.618f, -1.0f,
		0.0f, -2.618f, -1.0f, 0.0f, -2.618f, -1.0f, 0.0f, -2.618f, -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, 0.0f, -2.618f, -1.0f, 0.0f, -2.618f, -1.0f, 0.0f, -2.618f,
		1.0f, 0.0f, -2.618f, 1.0f, 0.0f, -2.618f, 1.0f, 0.0f, -2.618f,
		0.0f, 2.618f, 1.0f, 0.0f, 2.618f, 1.0f, 0.0f, 2.618f, 1.0f,
		0.0f, -2.618f, 1.0f, 0.0f, -2.618f, 1.0f, 0.0f, -2.618f, 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, 0.0f, 2.618f, -1.0f, 0.0f, 2.618f, -1.0f, 0.0f, 2.618f,
		1.0f, 0.0f, 2.618f, 1.0f, 0.0f, 2.618f, 1.0f, 0.0f, 2.618f,
		-2.618f, 1.0f, 0.0f, -2.618f, 1.0f, 0.0f, -2.618f, 1.0f, 0.0f,
		-2.618f, -1.0f, 0.0f, -2.618f, -1.0f, 0.0f, -2.618f, -1.0f, 0.0f,
		2.618f, 1.0f, 0.0f, 2.618f, 1.0f, 0.0f, 2.618f, 1.0f, 0.0f,
		2.618f, -1.0f, 0.0f, 2.618f, -1.0f, 0.0f, 2.618f, -1.0f, 0.0f
	};
	Object* obj = CreateObject(vm, 180, pos, color, v_pos, v_nor);
	return obj;
}
Object* CreateCube(Vertex_Manager* vm, glm::vec3 pos, glm::vec4 color) {
	float v_pos[108] = {
		-1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
		1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
		1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
		1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f,
		-1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
		-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
		-1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
		-1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f,
		-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f,
		1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
		1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
		-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f
	};
	float v_nor[108] = {
		0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
		0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
		1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
		1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
		0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
		0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
		-1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
		-1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
		0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
		0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
		0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f,
		0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f
	};
	Object* obj = CreateObject(vm, 108, pos, color, v_pos, v_nor);
	return obj;
}
Object* CreateCone(Vertex_Manager* vm, glm::vec3 pos, glm::vec4 color, float theta) {
	float q = PI / 30.0f;
	float tanTheta = tan(theta);
	float v_pos[1100], v_nor[1100];
	GLuint i = 0;
	for (float phi = -PI; phi < PI; phi += q) {
		v_pos[i + 0] = 0.0f;
		v_pos[i + 1] = 1.0f;
		v_pos[i + 2] = 0.0f;
		v_pos[i + 3] = cos(phi + q) * tanTheta * 2.0f;
		v_pos[i + 4] = -1.0f;
		v_pos[i + 5] = sin(phi + q) * tanTheta * 2.0f;
		v_pos[i + 6] = cos(phi) * tanTheta * 2.0f;
		v_pos[i + 7] = -1.0f;
		v_pos[i + 8] = sin(phi) * tanTheta * 2.0f;
		v_nor[i + 0] = cos(phi);
		v_nor[i + 1] = tanTheta;
		v_nor[i + 2] = sin(phi);
		v_nor[i + 3] = cos(phi + q);
		v_nor[i + 4] = tanTheta;
		v_nor[i + 5] = sin(phi + q);
		v_nor[i + 6] = cos(phi);
		v_nor[i + 7] = tanTheta;
		v_nor[i + 8] = sin(phi);
		i += 9;
	}
	Object* obj = CreateObject(vm, i, pos, color, v_pos, v_nor);
	return obj;
}
Object* CreateSphere(Vertex_Manager* vm, glm::vec3 pos, glm::vec4 color) {
	float q = PI / 30.0f;
	float* v_pos;
	GLuint i = 0;
	v_pos = new float[34100];
	for (float phi = -PI / 2.0f; phi < PI / 2.0f; phi += q)
		for (float theta = -PI; theta < PI; theta += q) {
			v_pos[i + 0] = cos(phi) * cos(theta + q);
			v_pos[i + 1] = sin(phi);
			v_pos[i + 2] = cos(phi) * sin(theta + q);
			v_pos[i + 3] = cos(phi) * cos(theta);
			v_pos[i + 4] = sin(phi);
			v_pos[i + 5] = cos(phi) * sin(theta);
			v_pos[i + 6] = cos(phi + q) * cos(theta);
			v_pos[i + 7] = sin(phi + q);
			v_pos[i + 8] = cos(phi + q) * sin(theta);
			v_pos[i + 9] = cos(phi + q) * cos(theta + q);
			v_pos[i + 10] = sin(phi + q);
			v_pos[i + 11] = cos(phi + q) * sin(theta + q);
			v_pos[i + 12] = cos(phi) * cos(theta + q);
			v_pos[i + 13] = sin(phi);
			v_pos[i + 14] = cos(phi) * sin(theta + q);
			v_pos[i + 15] = cos(phi + q) * cos(theta);
			v_pos[i + 16] = sin(phi + q);
			v_pos[i + 17] = cos(phi + q) * sin(theta);
			i += 18;
		}
	Object* obj = CreateObject(vm, i, pos, color, v_pos, v_pos);
	delete[] v_pos;
	return obj;
}
Object* CreateWaterDroplet(Vertex_Manager* vm, glm::vec3 pos, glm::vec4 color) {
	float q = PI / 30.0f;
	float a = sqrt(2.0f) - 1.0f;
	float x[21]{}, y[21]{}, d[21]{};
	float* v_pos;
	float* v_nor;
	v_pos = new float[40000];
	v_nor = new float[40000];
	GLuint i = 0;
	for (float phi = -PI / 2.0f; phi < 0; phi += q)
		for (float theta = -PI; theta < PI; theta += q) {
			v_pos[i + 0] = cos(phi) * cos(theta + q);
			v_pos[i + 1] = sin(phi);
			v_pos[i + 2] = cos(phi) * sin(theta + q);
			v_pos[i + 3] = cos(phi) * cos(theta);
			v_pos[i + 4] = sin(phi);
			v_pos[i + 5] = cos(phi) * sin(theta);
			v_pos[i + 6] = cos(phi + q) * cos(theta);
			v_pos[i + 7] = sin(phi + q);
			v_pos[i + 8] = cos(phi + q) * sin(theta);
			v_pos[i + 9] = cos(phi + q) * cos(theta + q);
			v_pos[i + 10] = sin(phi + q);
			v_pos[i + 11] = cos(phi + q) * sin(theta + q);
			v_pos[i + 12] = cos(phi) * cos(theta + q);
			v_pos[i + 13] = sin(phi);
			v_pos[i + 14] = cos(phi) * sin(theta + q);
			v_pos[i + 15] = cos(phi + q) * cos(theta);
			v_pos[i + 16] = sin(phi + q);
			v_pos[i + 17] = cos(phi + q) * sin(theta);
			v_nor[i + 0] = cos(phi) * cos(theta + q);
			v_nor[i + 1] = sin(phi);
			v_nor[i + 2] = cos(phi) * sin(theta + q);
			v_nor[i + 3] = cos(phi) * cos(theta);
			v_nor[i + 4] = sin(phi);
			v_nor[i + 5] = cos(phi) * sin(theta);
			v_nor[i + 6] = cos(phi + q) * cos(theta);
			v_nor[i + 7] = sin(phi + q);
			v_nor[i + 8] = cos(phi + q) * sin(theta);
			v_nor[i + 9] = cos(phi + q) * cos(theta + q);
			v_nor[i + 10] = sin(phi + q);
			v_nor[i + 11] = cos(phi + q) * sin(theta + q);
			v_nor[i + 12] = cos(phi) * cos(theta + q);
			v_nor[i + 13] = sin(phi);
			v_nor[i + 14] = cos(phi) * sin(theta + q);
			v_nor[i + 15] = cos(phi + q) * cos(theta);
			v_nor[i + 16] = sin(phi + q);
			v_nor[i + 17] = cos(phi + q) * sin(theta);
			i += 18;
		}
	for (int j = 0; j < 20; j++) {
		x[j] = sin(float(j) * PI / 40.0f);
		y[j] = (a + 1.0f) * (x[j] + a + 1.0f) * sqrt(1.0f - x[j] * x[j]) / (a + 2.0f) / (x[j] + a);
	}
	x[20] = 1.0f;
	y[20] = 0.0f;
	for (int j = 0; j < 20; j++)
		d[j] = -(x[j + 1] - x[j]) / (y[j + 1] - y[j]);
	d[20] = 0.0f;
	for (int j = 0; j < 20; j++)
		for (float phi = -PI; phi < PI; phi += q) {
			v_pos[i + 0] = cos(phi) * x[j];
			v_pos[i + 1] = y[j];
			v_pos[i + 2] = sin(phi) * x[j];
			v_pos[i + 3] = cos(phi + q) * x[j];
			v_pos[i + 4] = y[j];
			v_pos[i + 5] = sin(phi + q) * x[j];
			v_pos[i + 6] = cos(phi) * x[j + 1];
			v_pos[i + 7] = y[j + 1];
			v_pos[i + 8] = sin(phi) * x[j + 1];
			v_pos[i + 9] = cos(phi) * x[j + 1];
			v_pos[i + 10] = y[j + 1];
			v_pos[i + 11] = sin(phi) * x[j + 1];
			v_pos[i + 12] = cos(phi + q) * x[j];
			v_pos[i + 13] = y[j];
			v_pos[i + 14] = sin(phi + q) * x[j];
			v_pos[i + 15] = cos(phi + q) * x[j + 1];
			v_pos[i + 16] = y[j + 1];
			v_pos[i + 17] = sin(phi + q) * x[j + 1];
			v_nor[i + 0] = cos(phi);
			v_nor[i + 1] = d[j];
			v_nor[i + 2] = sin(phi);
			v_nor[i + 3] = cos(phi + q);
			v_nor[i + 4] = d[j];
			v_nor[i + 5] = sin(phi + q);
			v_nor[i + 6] = cos(phi);
			v_nor[i + 7] = d[j + 1];
			v_nor[i + 8] = sin(phi);
			v_nor[i + 9] = cos(phi);
			v_nor[i + 10] = d[j + 1];
			v_nor[i + 11] = sin(phi);
			v_nor[i + 12] = cos(phi + q);
			v_nor[i + 13] = d[j];
			v_nor[i + 14] = sin(phi + q);
			v_nor[i + 15] = cos(phi + q);
			v_nor[i + 16] = d[j + 1];
			v_nor[i + 17] = sin(phi + q);
			i += 18;
		}
	Object* obj = CreateObject(vm, i, pos, color, v_pos, v_nor);
	delete[] v_pos;
	delete[] v_nor;
	return obj;
}
Object* CreateSurface(Vertex_Manager* vm, glm::vec3 pos, glm::vec4 color, glm::vec3 p[4][4]) {
		glm::vec3 point[21][21]{};
		glm::vec3 normal[21][21]{};
		float* v_pos;
		float* v_nor;
		v_pos = new float[8000];
		v_nor = new float[8000];
		GLuint i = 0;
		for (int U = 0; U < 21; U++)
			for (int V = 0; V < 21; V++) {
				float u = (float)U / 20.0f;
				float v = (float)V / 20.0f;
				float bu[4] = { pow(1.0f - u, 3.0f), 3.0f * u * pow(1.0f - u, 2.0f), 3.0f * u * u * (1.0f - u), u * u * u };
				float bv[4] = { pow(1.0f - v, 3.0f), 3.0f * v * pow(1.0f - v, 2.0f), 3.0f * v * v * (1.0f - v), v * v * v };
				float dbu[4] = { -3.0f * pow(1.0f - u, 2.0f), 3.0f * (3.0f * u - 1.0f) * (u - 1.0f), 3.0f * u * (2.0f - 3.0f * u), 3 * u * u };
				float dbv[4] = { -3.0f * pow(1.0f - v, 2.0f), 3.0f * (3.0f * v - 1.0f) * (v - 1.0f), 3.0f * v * (2.0f - 3.0f * v), 3 * v * v };
				for (int x = 0; x < 4; x++)
					for (int y = 0; y < 4; y++) {
						point[U][V] += p[x][y] * bu[x] * bv[y];
					}
				glm::vec3 e1(0.0f, 0.0f, 0.0f), e2(0.0f, 0.0f, 0.0f);
				for (int x = 0; x < 4; x++)
					for (int y = 0; y < 4; y++) {
						e1 += p[x][y] * bu[x] * dbv[y];
						e2 += p[x][y] * dbu[x] * bv[y];
					}
				normal[U][V] = glm::cross(e1, e2);
			}
		for (int U = 0; U < 20; U++)
			for (int V = 0; V < 20; V++) {
				v_pos[i + 0] = point[U][V][0];
				v_pos[i + 1] = point[U][V][1];
				v_pos[i + 2] = point[U][V][2];
				v_pos[i + 3] = point[U][V + 1][0];
				v_pos[i + 4] = point[U][V + 1][1];
				v_pos[i + 5] = point[U][V + 1][2];
				v_pos[i + 6] = point[U + 1][V][0];
				v_pos[i + 7] = point[U + 1][V][1];
				v_pos[i + 8] = point[U + 1][V][2];
				v_pos[i + 9] = point[U + 1][V][0];
				v_pos[i + 10] = point[U + 1][V][1];
				v_pos[i + 11] = point[U + 1][V][2];
				v_pos[i + 12] = point[U][V + 1][0];
				v_pos[i + 13] = point[U][V + 1][1];
				v_pos[i + 14] = point[U][V + 1][2];
				v_pos[i + 15] = point[U + 1][V + 1][0];
				v_pos[i + 16] = point[U + 1][V + 1][1];
				v_pos[i + 17] = point[U + 1][V + 1][2];
				v_nor[i + 0] = normal[U][V][0];
				v_nor[i + 1] = normal[U][V][1];
				v_nor[i + 2] = normal[U][V][2];
				v_nor[i + 3] = normal[U][V + 1][0];
				v_nor[i + 4] = normal[U][V + 1][1];
				v_nor[i + 5] = normal[U][V + 1][2];
				v_nor[i + 6] = normal[U + 1][V][0];
				v_nor[i + 7] = normal[U + 1][V][1];
				v_nor[i + 8] = normal[U + 1][V][2];
				v_nor[i + 9] = normal[U + 1][V][0];
				v_nor[i + 10] = normal[U + 1][V][1];
				v_nor[i + 11] = normal[U + 1][V][2];
				v_nor[i + 12] = normal[U][V + 1][0];
				v_nor[i + 13] = normal[U][V + 1][1];
				v_nor[i + 14] = normal[U][V + 1][2];
				v_nor[i + 15] = normal[U + 1][V + 1][0];
				v_nor[i + 16] = normal[U + 1][V + 1][1];
				v_nor[i + 17] = normal[U + 1][V + 1][2];
				i += 18;
			}
	Object* obj = CreateObject(vm, i, pos, color, v_pos, v_nor);
	delete[] v_pos;
	delete[] v_nor;
	return obj;
}
void DrawObject(Camera* camera, Vertex_Manager* vm, Object* obj) {
	glm::mat4 mmat = glm::translate(glm::mat4(1.0f), obj->position);
	camera->mvmat = camera->vmat * mmat;
	camera->invmat = glm::transpose(glm::inverse(camera->mvmat));
	glUniformMatrix4fv(camera->mvloc, 1, GL_FALSE, glm::value_ptr(camera->mvmat));
	glUniformMatrix4fv(camera->ploc, 1, GL_FALSE, glm::value_ptr(camera->pmat));
	glUniformMatrix4fv(camera->nloc, 1, GL_FALSE, glm::value_ptr(camera->invmat));
	glUniform4fv(camera->cloc, 1, glm::value_ptr(obj->texture_color));
	glBindBuffer(GL_ARRAY_BUFFER, vm->vbo[obj->vbo_index[0]]);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);
	glBindBuffer(GL_ARRAY_BUFFER, vm->vbo[obj->vbo_index[1]]);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(1);
	glDrawArrays(GL_TRIANGLES, 0, obj->size / 3);
}
void DestroyObject(Object* obj) {
	delete obj->vertex_positions;
	delete obj->vertex_normals;
	delete obj;
	return;
}

noise.h

cpp 复制代码
#pragma once

#include <iostream>
#include <fstream>
#include <string>
#include <random>
#include <cmath>

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <soil2/SOIL2.h>

#ifndef PI
#define PI 3.14159f
#endif

#define M1 0
#define M2 1
#define D1 3
#define D2 4
#define MD 5
#define DM 6

GLuint CreateNoisyTexture256(glm::vec4 color1, glm::vec4 color2, GLubyte code) {
	float* smooth;
	float* layer[6];
	int pow2[6] = { 8, 16, 32, 64, 128, 256 };
	GLubyte* data;
	GLuint texture_id;
	smooth = new float[256 * 256 * 256];
	data = new GLubyte[256 * 256 * 256 * 4];
	for (int i = 0; i < 6; i++)
		layer[i] = new float[pow2[i] * pow2[i] * pow2[i]];
	for (GLuint i = 0; i < 6; i++) {
		for (GLuint x = 0; x < (GLuint)pow2[i]; x++)
			for (GLuint y = 0; y < (GLuint)pow2[i]; y++)
				for (GLuint z = 0; z < (GLuint)pow2[i]; z++)
					layer[i][x * pow2[i] * pow2[i] + y * pow2[i] + z] = float(rand() % 1025) / 256.0f / pow2[i];
	}
	for (GLuint x = 0; x < 256; x++) {
		for (GLuint y = 0; y < 256; y++)
			for (GLuint z = 0; z < 256; z++) {
				smooth[x * 256 * 256 + y * 256 + z] = 0.0f;
			}
	}
	for (GLuint i = 0; i < 6; i++) {
		for (GLuint x = 0; x < 256; x++)
			for (GLuint y = 0; y < 256; y++)
				for (GLuint z = 0; z < 256; z++) {
					float fx = float(x) / 256.0f * pow2[i] - 0.5f;
					float fy = float(y) / 256.0f * pow2[i] - 0.5f;
					float fz = float(z) / 256.0f * pow2[i] - 0.5f;
					int px = (int)floor(fx);
					int py = (int)floor(fy);
					int pz = (int)floor(fz);
					int nx = px + 1;
					int ny = py + 1;
					int nz = pz + 1;
					fx -= px;
					fy -= py;
					fz -= pz;
					if (px < 0) px += pow2[i];
					if (py < 0) py += pow2[i];
					if (pz < 0) pz += pow2[i];
					if (nx >= pow2[i]) nx -= pow2[i];
					if (ny >= pow2[i]) ny -= pow2[i];
					if (nz >= pow2[i]) nz -= pow2[i];
					smooth[x * 256 * 256 + y * 256 + z] +=
						fx * fy * fz * layer[i][nx * pow2[i] * pow2[i] + ny * pow2[i] + nz] +
						(1.0f - fx) * fy * fz * layer[i][px * pow2[i] * pow2[i] + ny * pow2[i] + nz] +
						fx * (1.0f - fy) * fz * layer[i][nx * pow2[i] * pow2[i] + py * pow2[i] + nz] +
						fx * fy * (1.0f - fz) * layer[i][nx * pow2[i] * pow2[i] + ny * pow2[i] + pz] +
						(1.0f - fx) * (1.0f - fy) * fz * layer[i][px * pow2[i] * pow2[i] + py * pow2[i] + nz] +
						(1.0f - fx) * fy * (1.0f - fz) * layer[i][px * pow2[i] * pow2[i] + ny * pow2[i] + pz] +
						fx * (1.0f - fy) * (1.0f - fz) * layer[i][nx * pow2[i] * pow2[i] + py * pow2[i] + pz] +
						(1.0f - fx) * (1.0f - fy) * (1.0f - fz) * layer[i][px * pow2[i] * pow2[i] + py * pow2[i] + pz];
				}
	}
	switch (code) {
		case M1: {
			for (GLuint x = 0; x < 256; x++) {
				for (GLuint y = 0; y < 256; y++)
					for (GLuint z = 0; z < 256; z++) {
						smooth[x * 256 * 256 + y * 256 + z] = sin(smooth[x * 256 * 256 + y * 256 + z] * PI * 0.5f);
					}
			}
			break;
		}
		case M2: {
			for (GLuint x = 0; x < 256; x++) {
				for (GLuint y = 0; y < 256; y++)
					for (GLuint z = 0; z < 256; z++) {
						smooth[x * 256 * 256 + y * 256 + z] = sin(smooth[x * 256 * 256 + y * 256 + z] * PI * 0.5f);
						smooth[x * 256 * 256 + y * 256 + z] = sin(smooth[x * 256 * 256 + y * 256 + z] * PI * 0.5f);
					}
			}
			break;
		}
		case D1: {
			for (GLuint x = 0; x < 256; x++) {
				for (GLuint y = 0; y < 256; y++)
					for (GLuint z = 0; z < 256; z++) {
						smooth[x * 256 * 256 + y * 256 + z] = 0.5f - 0.5f * cos(smooth[x * 256 * 256 + y * 256 + z] * PI);
					}
			}
			break;
		}
		case D2: {
			for (GLuint x = 0; x < 256; x++) {
				for (GLuint y = 0; y < 256; y++)
					for (GLuint z = 0; z < 256; z++) {
						smooth[x * 256 * 256 + y * 256 + z] = 0.5f - 0.5f * cos(smooth[x * 256 * 256 + y * 256 + z] * PI);
						smooth[x * 256 * 256 + y * 256 + z] = 0.5f - 0.5f * cos(smooth[x * 256 * 256 + y * 256 + z] * PI);
					}
			}
			break;
		}
		case MD: {
			for (GLuint x = 0; x < 256; x++) {
				for (GLuint y = 0; y < 256; y++)
					for (GLuint z = 0; z < 256; z++) {
						smooth[x * 256 * 256 + y * 256 + z] = sin(smooth[x * 256 * 256 + y * 256 + z] * PI * 0.5f);
						smooth[x * 256 * 256 + y * 256 + z] = 0.5f - 0.5f * cos(smooth[x * 256 * 256 + y * 256 + z] * PI);
					}
			}
			break;
		}
		case DM: {
			for (GLuint x = 0; x < 256; x++) {
				for (GLuint y = 0; y < 256; y++)
					for (GLuint z = 0; z < 256; z++) {
						smooth[x * 256 * 256 + y * 256 + z] = 0.5f - 0.5f * cos(smooth[x * 256 * 256 + y * 256 + z] * PI);
						smooth[x * 256 * 256 + y * 256 + z] = sin(smooth[x * 256 * 256 + y * 256 + z] * PI * 0.5f);
					}
			}
			break;
		}
	}

	for (GLuint x = 0; x < 256; x++) {
		for (GLuint y = 0; y < 256; y++)
			for (GLuint z = 0; z < 256; z++) {
				data[x * 256 * 256 * 4 + y * 256 * 4 + z * 4 + 0] =
					GLubyte(smooth[x * 256 * 256 + y * 256 + z] * color1[0] * 255.0f + (1.0f - smooth[x * 256 * 256 + y * 256 + z]) * color2[0] * 255.0f);
				data[x * 256 * 256 * 4 + y * 256 * 4 + z * 4 + 1] =
					GLubyte(smooth[x * 256 * 256 + y * 256 + z] * color1[1] * 255.0f + (1.0f - smooth[x * 256 * 256 + y * 256 + z]) * color2[1] * 255.0f);
				data[x * 256 * 256 * 4 + y * 256 * 4 + z * 4 + 2] =
					GLubyte(smooth[x * 256 * 256 + y * 256 + z] * color1[2] * 255.0f + (1.0f - smooth[x * 256 * 256 + y * 256 + z]) * color2[2] * 255.0f);
				data[x * 256 * 256 * 4 + y * 256 * 4 + z * 4 + 3] =
					GLubyte(smooth[x * 256 * 256 + y * 256 + z] * color1[3] * 255.0f + (1.0f - smooth[x * 256 * 256 + y * 256 + z]) * color2[3] * 255.0f);
			}
	}
	glGenTextures(1, &texture_id);
	glBindTexture(GL_TEXTURE_3D, texture_id);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 256, 256, 256);
	glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 256, 256, 256, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
	for (GLuint i = 0; i < 6; i++)
		delete[] layer[i];
	delete[] smooth;
	delete[] data;
	return texture_id;
}

vert_shader.glsl

cpp 复制代码
#version 430

layout (location=0) in vec3 position;
layout (location=1) in vec3 normal;

out vec3 varying_normal;
out vec3 varying_direction;
out vec3 varying_vertpos;

uniform mat4 mvmat;
uniform mat4 pmat;
uniform mat4 nmat;
uniform vec4 texture_color;

uniform vec4 GlobalAmbient;
uniform vec4 DirLightAmbient;
uniform vec4 DirLightDiffuse;
uniform vec4 DirLightSpecular;
uniform vec3 DirLightDirection;

void main(void) {
	varying_direction = (nmat * vec4(-DirLightDirection, 1.0)).xyz;
	varying_vertpos = -(mvmat * vec4(position, 1.0)).xyz;
	varying_normal = (nmat * vec4(normal, 1.0)).xyz;
	gl_Position = pmat * mvmat * vec4(position, 1.0);
}

frag_shader.glsl

cpp 复制代码
#version 430

in vec3 varying_normal;
in vec3 varying_direction;
in vec3 varying_vertpos;

out vec4 color;

uniform mat4 mvmat;
uniform mat4 pmat;
uniform mat4 nmat;
uniform vec4 texture_color;

uniform vec4 GlobalAmbient;
uniform vec4 DirLightAmbient;
uniform vec4 DirLightDiffuse;
uniform vec4 DirLightSpecular;
uniform vec3 DirLightDirection;

void main(void) {
	vec3 L = normalize(varying_direction);
	vec3 N = normalize(varying_normal);
	vec3 V = normalize(varying_vertpos);
	vec3 H = normalize(L + V);
	float cos_theta = dot(L, N);
	float cos_phi = dot(N, H);
	float flag = float(texture_color[3] <= 0.001);
	vec3 ambient = GlobalAmbient.xyz * texture_color.xyz + DirLightAmbient.xyz * texture_color.xyz;
	vec3 diffuse = texture_color.xyz * DirLightDiffuse.xyz * (max(cos_theta, 0.0) * (flag * 0.6 + 0.4));
	vec3 specular = texture_color.xyz * DirLightSpecular.xyz * pow(max(cos_phi, 0.001), 3.0 * texture_color[3]) * (1.0 - flag);
	color = vec4(ambient + diffuse + specular, 1.0);
}

sky_vert.glsl

cpp 复制代码
#version 430

layout (location=0) in vec3 position;
layout (binding=0) uniform sampler3D sampler;

out vec3 original_position;

uniform mat4 mvmat;
uniform mat4 pmat;

void main(void) {
	original_position = position;
	gl_Position = pmat * mvmat * vec4(position, 1.0);
}

sky_frag.glsl

cpp 复制代码
#version 430

layout (binding=0) uniform sampler3D sampler;

in vec3 original_position;
out vec4 color;

uniform mat4 mvmat;
uniform mat4 pmat;

void main(void) {
	color = texture(sampler, original_position * 0.5 + 0.5);
}

snow_vert.glsl

cpp 复制代码
#version 430

layout (location=0) in vec3 position;

uniform mat4 mvmat;
uniform mat4 pmat;
uniform vec4 texture_color;
uniform float current_time;

float random(float seed) {
	return 1025.0 * sin(seed) - floor(1025.0 * sin(seed));
}

void main(void) {
	float rate = random(float(gl_InstanceID) * 0.7) * 0.5 + 0.5;
	float size = random(float(gl_InstanceID) * 0.9) * 0.3 + 0.3;
	float phi = current_time * 2.0 + random(float(gl_InstanceID) * 1.1);
	float theta = current_time * 3.0 + random(float(gl_InstanceID) * 1.3);
	float rx = 64.0 * random(float(gl_InstanceID) * 1.5) - 32.0;
	float rz = 64.0 * random(float(gl_InstanceID) * 1.7) - 32.0;
	float ry =  current_time * 0.125 * rate + random(float(gl_InstanceID) * 1.9) - floor(current_time * 0.125 * rate + random(float(gl_InstanceID) * 1.9));
	ry = 32.0 - ry * 64.0;
	mat4 tmat = mat4(
		size, 0, 0, 0,
		0, size, 0, 0,
		0, 0, size, 0,
		rx, ry, rz, 1
	);
	mat4 rmat1 = mat4(
		cos(phi), sin(phi), 0, 0,
		-sin(phi), cos(phi), 0, 0,
		0, 0, 1, 0,
		0, 0, 0, 1
	);
	mat4 rmat2 = mat4(
		cos(theta), 0, sin(theta), 0,
		0, 1, 0, 0,
		-sin(theta), 0, cos(theta), 0,
		0, 0, 0, 1
	);
	gl_Position = pmat * mvmat * tmat * rmat2 * rmat1 * vec4(position, 1.0);
}

snow_frag.glsl

cpp 复制代码
#version 430

out vec4 color;

uniform mat4 mvmat;
uniform mat4 pmat;
uniform vec4 texture_color;
uniform float current_time;

void main(void) {
	color = texture_color;
}
相关推荐
郁闷的网纹蟒2 小时前
虚幻5---第12部分---蒙太奇
开发语言·c++·ue5·游戏引擎·虚幻
u0109272712 小时前
实时数据流处理
开发语言·c++·算法
Trouvaille ~3 小时前
【Linux】线程同步与互斥(一):线程互斥原理与mutex详解
linux·运维·服务器·c++·算法·线程·互斥锁
软件资深者3 小时前
在游戏中显示 FPS工具,检测硬件性能,排查游戏卡顿神器
游戏
Queenie_Charlie3 小时前
位移运算
c++·位运算
hurrycry_小亦3 小时前
洛谷题目:P1365 WJMZBMR打osu! / Easy 题解(本题较简)
c++
m0_748708053 小时前
C++代码移植性设计
开发语言·c++·算法
郝学胜-神的一滴3 小时前
Linux Socket模型创建流程详解
linux·服务器·开发语言·网络·c++·程序人生
王老师青少年编程3 小时前
2024信奥赛C++提高组csp-s复赛真题及题解:决斗
c++·真题·csp·信奥赛·csp-s·提高组·决斗