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