性能问题:
帧率仅35, 经过计时问题在这行代码
glBindFramebuffer(GL_FRAMEBUFFER, shadow_buffer); //这行代码耗费了0.02s!!!
```c++
static void SetupBuffers(GLFWwindow* window, GLuint* buffer, GLuint* depth, GLuint* texture) {
GLuint buffer_id[1]{};
glGenBuffers(1, buffer_id);
glfwGetFramebufferSize(window, &WIDTH, &HEIGHT);
glGenFramebuffers(1, buffer_id);
*buffer = buffer_id[0];
glBindFramebuffer(GL_FRAMEBUFFER, *buffer);
glGenTextures(1, buffer_id);
*texture = buffer_id[0];
glBindTexture(GL_TEXTURE_2D, *texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texture, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glGenTextures(1, buffer_id);
*depth = buffer_id[0];
glBindTexture(GL_TEXTURE_2D, *depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, WIDTH, HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, *depth, 0);
}
static void init(GLFWwindow* window) {
camera.vmat = glm::mat4(1.0f);
camera.tmat = glm::mat4(1.0f);
camera.rmat = glm::mat4(1.0f);
camera.pmat = glm::perspective(1.4f, aspect, 2000.0f, 0.2f);
reflect_camera.vmat = glm::mat4(1.0f);
reflect_camera.tmat = glm::mat4(1.0f);
reflect_camera.rmat = glm::mat4(1.0f);
reflect_camera.pmat = glm::perspective(1.4f, aspect, 2000.0f, 0.2f);
proj_mat = ortho_matrix(sunshine.direction, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
rendering_program = CreateShaderProgram("vert_shader.glsl", "frag_shader.glsl");
grassland_program = CreateShaderProgram("grass_vert.glsl", "grass_frag.glsl");
shadow_program = CreateShaderProgram("shadow_vert.glsl", "shadow_frag.glsl");
water_program = CreateShaderProgram("water_vert.glsl", "water_frag.glsl");
plain_program = CreateShaderProgram("plain_vert.glsl", "plain_frag.glsl");
snow_program = CreateShaderProgram("snow_vert.glsl", "snow_frag.glsl");
sky_program = CreateShaderProgram("sky_vert.glsl", "sky_frag.glsl");
sky_texture = CreateNoisy3DTexture(glm::vec4(0.0f, 0.5f, 1.0f, 1.0f), glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), 256, MD);
water_texture = CreateNoisy3DHeight(256, NULL, [](float x, float y, float z) -> float{ return 0.5f * sin(x * 32.0f * PI) * sin(z * 32.0f * PI) - 0.5f; });
grass_texture = CreateRandom2DTexture(128);
snow_texture = CreateRandom2DTexture(512);
SetupBuffers(window, &shadow_buffer, &shadow_depth, &shadow_texture);
SetupBuffers(window, &reflect_buffer, &reflect_depth, &reflect_texture);
SetupBuffers(window, &refract_buffer, &refract_depth, &refract_texture);
glGenVertexArrays(numVAOs, vm.vao);
glBindVertexArray(vm.vao[0]);
glGenBuffers(numVBOs, vm.vbo);
glClearDepth(0.0f);
glClearColor(0.7f, 0.7f, 0.7f, 1.0f);
square = CreateSquare(&vm, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f));
water = CreateSquare(&vm, glm::vec3(0.0f, 1.0f, 0.0f), glm::vec4(0.0f, 0.0f, 1.0f, 1.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, 1.0f), PI / 6.0f);
grass = CreateGrass(&vm, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.6f, 0.0f, 0.0f));
float* chunk = new float[80000];
sky = CreateSphere(&vm, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), chunk, 80000);
sphere = CreateSphere(&vm, glm::vec3(6.0f, 10.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), chunk, 80000);
water_droplet = CreateWaterDroplet(&vm, glm::vec3(6.0f, 12.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), chunk, 80000);
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, 0.0f, 2.0f),
glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec3(0.0f, 0.0f, 2.0f),
glm::vec3(1.0f, 0.0f, -1.0f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 0.0f, 2.0f),
glm::vec3(2.0f, 0.0f, -1.0f), glm::vec3(2.0f, 0.0f, 0.0f), glm::vec3(2.0f, 0.0f, 1.0f), glm::vec3(2.0f, 0.0f, 2.0f)
};
surface = CreateSurface(&vm, glm::vec3(0.0f, 4.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), p, chunk, 80000);
penguin = CreatePenguin(&vm, chunk, 80000);
delete[] chunk;
}
static void WindowReshapeCallback(GLFWwindow* window, int new_width, int new_height) {
WIDTH = new_width;
HEIGHT = new_height;
aspect = (float)WIDTH / (float)HEIGHT;
glViewport(0, 0, WIDTH, HEIGHT);
camera.pmat = glm::perspective(1.4f, aspect, 2000.0f, 0.2f);
glDeleteTextures(1, &shadow_depth);
glDeleteTextures(1, &shadow_texture);
glDeleteFramebuffers(1, &shadow_buffer);
SetupBuffers(window, &shadow_buffer, &shadow_depth, &shadow_texture);
reflect_camera.pmat = glm::perspective(1.4f, aspect, 2000.0f, 0.2f);
glDeleteTextures(1, &reflect_depth);
glDeleteTextures(1, &reflect_texture);
glDeleteFramebuffers(1, &reflect_buffer);
SetupBuffers(window, &reflect_buffer, &reflect_depth, &reflect_texture);
glDeleteTextures(1, &refract_depth);
glDeleteTextures(1, &refract_texture);
glDeleteFramebuffers(1, &refract_buffer);
SetupBuffers(window, &refract_buffer, &refract_depth, &refract_texture);
}
static void InstallLight(GLuint program) {
global_amb_loc = glGetUniformLocation(program, "GlobalAmbient");
sunshine.dirlight_amb_loc = glGetUniformLocation(program, "DirLightAmbient");
sunshine.dirlight_dif_loc = glGetUniformLocation(program, "DirLightDiffuse");
sunshine.dirlight_spe_loc = glGetUniformLocation(program, "DirLightSpecular");
sunshine.dirlight_dir_loc = glGetUniformLocation(program, "DirLightDirection");
glProgramUniform4fv(program, global_amb_loc, 1, glm::value_ptr(global_ambient));
glProgramUniform4fv(program, sunshine.dirlight_amb_loc, 1, glm::value_ptr(sunshine.direction_light_ambient));
glProgramUniform4fv(program, sunshine.dirlight_dif_loc, 1, glm::value_ptr(sunshine.direction_light_diffuse));
glProgramUniform4fv(program, sunshine.dirlight_spe_loc, 1, glm::value_ptr(sunshine.direction_light_specular));
glProgramUniform3fv(program, sunshine.dirlight_dir_loc, 1, glm::value_ptr(sunshine.direction));
}
static void InstallCamera(GLuint program, Camera* came) {
came->mvloc = glGetUniformLocation(program, "mvmat");
came->ploc = glGetUniformLocation(program, "pmat");
came->vloc = glGetUniformLocation(program, "vmat");
came->cloc = glGetUniformLocation(program, "texture_color");
}
static void process1(Camera* came, double current_time) {
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
if (weather == sunny) {
glUseProgram(sky_program);
temp_location = glGetUniformLocation(sky_program, "light_angle");
came->vloc = glGetUniformLocation(sky_program, "light_direction"); //临时替用
came->mvloc = glGetUniformLocation(sky_program, "mvmat");
came->ploc = glGetUniformLocation(sky_program, "pmat");
came->mvmat = came->vmat * glm::translate(glm::mat4(1.0f), came->position);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, sky_texture);
glUniform1f(temp_location, direction_light_angle);
glUniform3fv(came->vloc, 1, glm::value_ptr(sunshine.direction));
glUniformMatrix4fv(came->mvloc, 1, GL_FALSE, glm::value_ptr(came->mvmat));
glUniformMatrix4fv(came->ploc, 1, GL_FALSE, glm::value_ptr(came->pmat));
glBindBuffer(GL_ARRAY_BUFFER, vm.vbo[sky->vbo_index[0]]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, sky->size / 3);
}
#ifdef DEBUG
using_time[run_times][program_num++] = glfwGetTime() - debug_pre;
debug_pre = glfwGetTime();
#endif
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_GEQUAL);
glUseProgram(rendering_program);
InstallLight(rendering_program);
InstallCamera(rendering_program, came);
DrawObject(came, &vm, cone);
DrawObject(came, &vm, surface);
glEnable(GL_CULL_FACE);
DrawObject(came, &vm, cube);
DrawObject(came, &vm, tetrahedron);
DrawObject(came, &vm, icosahedron);
DrawObject(came, &vm, sphere);
DrawObject(came, &vm, water_droplet);
#ifdef DEBUG
using_time[run_times][program_num++] = glfwGetTime() - debug_pre;
debug_pre = glfwGetTime();
#endif
}
static void process2(Camera* came, double current_time) {
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glDisable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_GEQUAL);
glUseProgram(plain_program);
InstallLight(plain_program);
came->mvloc = glGetUniformLocation(plain_program, "mvmat");
came->ploc = glGetUniformLocation(plain_program, "pmat");
came->vloc = glGetUniformLocation(plain_program, "vmat");
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, shadow_texture);
came->mvmat = came->vmat * glm::translate(glm::mat4(1.0f), square->position);
glUniformMatrix4fv(came->mvloc, 1, GL_FALSE, glm::value_ptr(came->mvmat));
glUniformMatrix4fv(came->ploc, 1, GL_FALSE, glm::value_ptr(came->pmat));
glUniformMatrix4fv(came->vloc, 1, GL_FALSE, glm::value_ptr(came->vmat));
glBindBuffer(GL_ARRAY_BUFFER, vm.vbo[square->vbo_index[0]]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vm.vbo[square->vbo_index[1]]);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glDrawArrays(GL_TRIANGLES, 0, square->size / 3);
#ifdef DEBUG
using_time[run_times][program_num++] = glfwGetTime() - debug_pre;
debug_pre = glfwGetTime();
#endif
glUseProgram(grassland_program);
global_amb_loc = glGetUniformLocation(grassland_program, "GlobalAmbient");
sunshine.dirlight_amb_loc = glGetUniformLocation(grassland_program, "DirLightAmbient");
sunshine.dirlight_dif_loc = glGetUniformLocation(grassland_program, "DirLightDiffuse");
sunshine.dirlight_dir_loc = glGetUniformLocation(grassland_program, "DirLightDirection");
glProgramUniform4fv(grassland_program, global_amb_loc, 1, glm::value_ptr(global_ambient));
glProgramUniform4fv(grassland_program, sunshine.dirlight_amb_loc, 1, glm::value_ptr(sunshine.direction_light_ambient));
glProgramUniform4fv(grassland_program, sunshine.dirlight_dif_loc, 1, glm::value_ptr(sunshine.direction_light_diffuse));
glProgramUniform3fv(grassland_program, sunshine.dirlight_dir_loc, 1, glm::value_ptr(sunshine.direction));
InstallCamera(grassland_program, came);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, shadow_texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, grass_texture);
came->mvmat = came->vmat * glm::translate(glm::mat4(1.0f), grass->position);
glUniformMatrix4fv(came->mvloc, 1, GL_FALSE, glm::value_ptr(came->mvmat));
glUniformMatrix4fv(came->ploc, 1, GL_FALSE, glm::value_ptr(came->pmat));
glUniformMatrix4fv(came->vloc, 1, GL_FALSE, glm::value_ptr(came->vmat));
glUniform4fv(came->cloc, 1, glm::value_ptr(grass->texture_color));
glBindBuffer(GL_ARRAY_BUFFER, vm.vbo[grass->vbo_index[0]]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vm.vbo[grass->vbo_index[1]]);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glDrawArraysInstanced(GL_TRIANGLES, 0, grass->size / 3, 16384);
#ifdef DEBUG
using_time[run_times][program_num++] = glfwGetTime() - debug_pre;
debug_pre = glfwGetTime();
#endif
glUseProgram(rendering_program);
InstallLight(rendering_program);
InstallCamera(rendering_program, came);
glEnable(GL_CULL_FACE);
DrawModel(came, &vm, penguin->penguin_model, glm::translate(glm::mat4(1.0f), penguin->penguin_model->position) * glm::rotate(glm::mat4(1.0f), PI, glm::vec3(0.0f, 1.0f, 0.0f)));
#ifdef DEBUG
using_time[run_times][program_num++] = glfwGetTime() - debug_pre;
debug_pre = glfwGetTime();
#endif
}
static void process3(Camera* came, double current_time) {
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
if (weather == sunny) {
glUseProgram(sky_program);
temp_location = glGetUniformLocation(sky_program, "light_angle");
came->vloc = glGetUniformLocation(sky_program, "light_direction"); //临时替用
came->mvloc = glGetUniformLocation(sky_program, "mvmat");
came->ploc = glGetUniformLocation(sky_program, "pmat");
came->mvmat = came->vmat * glm::translate(glm::mat4(1.0f), came->position);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, sky_texture);
glUniform1f(temp_location, direction_light_angle);
glUniform3fv(came->vloc, 1, glm::value_ptr(sunshine.direction));
glUniformMatrix4fv(came->mvloc, 1, GL_FALSE, glm::value_ptr(came->mvmat));
glUniformMatrix4fv(came->ploc, 1, GL_FALSE, glm::value_ptr(came->pmat));
glBindBuffer(GL_ARRAY_BUFFER, vm.vbo[sky->vbo_index[0]]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, sky->size / 3);
}
#ifdef DEBUG
using_time[run_times][program_num++] = glfwGetTime() - debug_pre;
debug_pre = glfwGetTime();
#endif
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_GEQUAL);
if (weather == snowy) {
glUseProgram(snow_program);
temp_location = glGetUniformLocation(snow_program, "camera");
time_location = glGetUniformLocation(snow_program, "current_time");
came->mvloc = glGetUniformLocation(snow_program, "mvmat");
came->ploc = glGetUniformLocation(snow_program, "pmat");
came->mvmat = came->vmat;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, snow_texture);
glUniformMatrix4fv(came->mvloc, 1, GL_FALSE, glm::value_ptr(came->mvmat));
glUniformMatrix4fv(came->ploc, 1, GL_FALSE, glm::value_ptr(came->pmat));
glUniform3fv(temp_location, 1, glm::value_ptr(came->position));
glUniform1f(time_location, (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, 262144);
}
#ifdef DEBUG
using_time[run_times][program_num++] = glfwGetTime() - debug_pre;
debug_pre = glfwGetTime();
#endif
glUseProgram(plain_program);
InstallLight(plain_program);
came->mvloc = glGetUniformLocation(plain_program, "mvmat");
came->ploc = glGetUniformLocation(plain_program, "pmat");
came->vloc = glGetUniformLocation(plain_program, "vmat");
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, shadow_texture);
came->mvmat = came->vmat * glm::translate(glm::mat4(1.0f), square->position);
glUniformMatrix4fv(came->mvloc, 1, GL_FALSE, glm::value_ptr(came->mvmat));
glUniformMatrix4fv(came->ploc, 1, GL_FALSE, glm::value_ptr(came->pmat));
glUniformMatrix4fv(came->vloc, 1, GL_FALSE, glm::value_ptr(came->vmat));
glBindBuffer(GL_ARRAY_BUFFER, vm.vbo[square->vbo_index[0]]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vm.vbo[square->vbo_index[1]]);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glDrawArrays(GL_TRIANGLES, 0, square->size / 3);
#ifdef DEBUG
using_time[run_times][program_num++] = glfwGetTime() - debug_pre;
debug_pre = glfwGetTime();
#endif
glUseProgram(grassland_program);
InstallLight(grassland_program);
InstallCamera(grassland_program, came);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, shadow_texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, grass_texture);
came->mvmat = came->vmat * glm::translate(glm::mat4(1.0f), grass->position);
glUniformMatrix4fv(came->mvloc, 1, GL_FALSE, glm::value_ptr(came->mvmat));
glUniformMatrix4fv(came->ploc, 1, GL_FALSE, glm::value_ptr(came->pmat));
glUniformMatrix4fv(came->vloc, 1, GL_FALSE, glm::value_ptr(came->vmat));
glUniform4fv(came->cloc, 1, glm::value_ptr(grass->texture_color));
glBindBuffer(GL_ARRAY_BUFFER, vm.vbo[grass->vbo_index[0]]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vm.vbo[grass->vbo_index[1]]);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glDrawArraysInstanced(GL_TRIANGLES, 0, grass->size / 3, 16384);
#ifdef DEBUG
using_time[run_times][program_num++] = glfwGetTime() - debug_pre;
debug_pre = glfwGetTime();
#endif
glUseProgram(rendering_program);
InstallLight(rendering_program);
InstallCamera(rendering_program, came);
DrawObject(came, &vm, cone);
DrawObject(came, &vm, surface);
glEnable(GL_CULL_FACE);
DrawObject(came, &vm, cube);
DrawObject(came, &vm, tetrahedron);
DrawObject(came, &vm, icosahedron);
DrawObject(came, &vm, sphere);
DrawObject(came, &vm, water_droplet);
DrawModel(came, &vm, penguin->penguin_model, glm::translate(glm::mat4(1.0f), penguin->penguin_model->position) * glm::rotate(glm::mat4(1.0f), PI, glm::vec3(0.0f, 1.0f, 0.0f)));
#ifdef DEBUG
using_time[run_times][program_num++] = glfwGetTime() - debug_pre;
debug_pre = glfwGetTime();
#endif
}
static void display(GLFWwindow* window, double current_time) {
#ifdef DEBUG
program_num = 0;
debug_pre = glfwGetTime();
#endif
/*第一轮:绘制阴影,记录颜色*/
glBindFramebuffer(GL_FRAMEBUFFER, shadow_buffer); //这行代码耗费了0.02s!!!
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glUseProgram(shadow_program);
camera.mvloc = glGetUniformLocation(shadow_program, "mat");
/*绘制除水,平面,草坪以外的物体*/
glm::mat4 temp_mat = camera.pmat * camera.vmat * proj_mat;
DrawShadow(&camera, &vm, cone, temp_mat * glm::translate(glm::mat4(1.0f), cone->position));
DrawShadow(&camera, &vm, surface, temp_mat * glm::translate(glm::mat4(1.0f), surface->position));
DrawShadow(&camera, &vm, cube, temp_mat * glm::translate(glm::mat4(1.0f), cube->position));
DrawShadow(&camera, &vm, tetrahedron, temp_mat * glm::translate(glm::mat4(1.0f), tetrahedron->position));
DrawShadow(&camera, &vm, icosahedron, temp_mat * glm::translate(glm::mat4(1.0f), icosahedron->position));
DrawShadow(&camera, &vm, sphere, temp_mat * glm::translate(glm::mat4(1.0f), sphere->position));
DrawShadow(&camera, &vm, water_droplet, temp_mat * glm::translate(glm::mat4(1.0f), water_droplet->position));
DrawShadow(&camera, &vm, penguin->penguin_model, temp_mat * glm::translate(glm::mat4(1.0f), penguin->penguin_model->position) *
glm::rotate(glm::mat4(1.0f), PI, glm::vec3(0.0f, 1.0f, 0.0f)));
#ifdef DEBUG
using_time[run_times][program_num++] = glfwGetTime() - debug_pre;
debug_pre = glfwGetTime();
#endif
//第二轮:绘制反射,记录颜色
glBindFramebuffer(GL_FRAMEBUFFER, reflect_buffer);
//不绘制雪,水面以下物体
process1(&reflect_camera, current_time);
//第三轮:绘制折射,记录颜色
glBindFramebuffer(GL_FRAMEBUFFER, refract_buffer);
//不绘制雪,水面以上的物体
process2(&camera, current_time);
//第三轮:绘制除阴影外的物体
glBindFramebuffer(GL_FRAMEBUFFER, 0);
process3(&camera, current_time);
glDisable(GL_CULL_FACE);
glUseProgram(water_program);
camera.mvmat = camera.vmat * glm::translate(glm::mat4(1.0f), water->position);
camera.mvloc = glGetUniformLocation(water_program, "mvmat");
camera.ploc = glGetUniformLocation(water_program, "pmat");
camera.cloc = glGetUniformLocation(water_program, "texture_color");
temp_location = glGetUniformLocation(water_program, "camera");
time_location = glGetUniformLocation(water_program, "time");
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, reflect_texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, refract_texture);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_3D, water_texture);
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(water->texture_color));
glUniform3fv(temp_location, 1, glm::value_ptr(camera.position - water->position));
glUniform1f(time_location, (GLfloat)current_time);
glBindBuffer(GL_ARRAY_BUFFER, vm.vbo[water->vbo_index[0]]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, water->size / 3);
#ifdef DEBUG
using_time[run_times][program_num++] = glfwGetTime() - debug_pre;
debug_pre = glfwGetTime();
#endif
}
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();
#ifndef DEBUG
while (glfwGetTime() - pre <= 0.02);
std::cout << "FPS:" << 1.0 / (glfwGetTime() - pre) << std::endl; //帧率
#else
run_times++;
std::cout << "FPS:" << 1.0 / (glfwGetTime() - pre) << std::endl; //帧率
#endif
pre = glfwGetTime();
}
DestroyObject(square);
DestroyObject(water);
DestroyObject(snow);
DestroyObject(tetrahedron);
DestroyObject(icosahedron);
DestroyObject(cube);
DestroyObject(cone);
DestroyObject(grass);
DestroyObject(sky);
DestroyObject(sphere);
DestroyObject(water_droplet);
DestroyObject(surface);
DestroyModel(penguin->penguin_model);
#ifdef DEBUG
double sum[32]{};
std::fstream fout("analysis.txt", std::ios::out);
for (GLuint i = 0; i < program_num; i++)
sum[i] = 0.0f;
for (GLuint i = 0; i < program_num; i++) {
for (GLuint j = 256; j < run_times; j++) //除去前256次
sum[i] += using_time[j][i];
sum[i] /= double(run_times - 256);
}
fout << "shadow_program:" << sum[0] << std::endl;
fout << "process1-sky_program:" << sum[1] << std::endl;
fout << "process1-rendering_program:" << sum[2] << std::endl;
fout << "process2-plain_program:" << sum[3] << std::endl;
fout << "process2-grassland_program:" << sum[4] << std::endl;
fout << "process2-rendering_program:" << sum[5] << std::endl;
fout << "process3-sky_program:" << sum[6] << std::endl;
fout << "process3-snow_program:" << sum[7] << std::endl;
fout << "process3-plain_program:" << sum[8] << std::endl;
fout << "process3-grassland_program:" << sum[9] << std::endl;
fout << "process3-rendering_program:" << sum[10] << std::endl;
fout << "water_program:" << sum[11] << std::endl;
fout.close();
#endif
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
```