static void draw_buffer(SmokeDomainSettings *sds, GPUShader *shader, const VolumeSlicer *slicer, const float ob_sizei[3], const float invsize[3], const int num_points, const bool do_fire) { GPUTexture *tex_spec = (do_fire) ? create_flame_spectrum_texture() : NULL; GLuint vertex_buffer; glGenBuffers(1, &vertex_buffer); glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * num_points, &slicer->verts[0][0], GL_STATIC_DRAW); bind_shader(sds, shader, tex_spec, do_fire, slicer->min, ob_sizei, invsize); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, NULL); glDrawArrays(GL_TRIANGLES, 0, num_points); glDisableClientState(GL_VERTEX_ARRAY); unbind_shader(sds, tex_spec, do_fire); /* cleanup */ glBindBuffer(GL_ARRAY_BUFFER, 0); glDeleteBuffers(1, &vertex_buffer); }
int initialize() { GLint loc; float point[4] = {0.0f, 0.0f, 0.0f, 0.0f}; tetrahedron4x4_t hypercube[hypercube_size * 2]; glClearColor(0.1f, 0.15f, 0.2f, 1.0f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glViewport(0, 0, modes->hdisplay, modes->vdisplay); //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); running = 1; create_shader(&shader); load_shader(shader, "tetrahedron_vs.glsl", shader_type_vertex); load_shader(shader, "tetrahedron_gs.glsl", shader_type_geometry); load_shader(shader, "tetrahedron_fs.glsl", shader_type_fragment); shaders_loaded_to_shader(shader); bind_shader(shader); create_hypercube(hypercube); create_hypercube(&hypercube[hypercube_size]); prepare_tetrahedrons(shader, (tetrahedron4x4_t *)&hypercube, hypercube_size * 2); getuniformslot_shader(shader, &loc, "view_shift"); exts.glUniform4fv(loc, 1, point); getuniformslot_shader(shader, &loc, "view"); general_rotate(view, 1, 2, 3.14f / 6.0f); general_rotate(view, 1, 3, 3.14f / 6.0f); general_rotate(view, 0, 1, 3.14f / 3.0f); general_rotate(view, 2, 3, 3.14f / 5.0f); exts.glUniformMatrix4fv(loc, 1, GL_FALSE, view); getuniformslot_shader(shader, &loc, "invview"); general_inverse(view, 4); exts.glUniformMatrix4fv(loc, 1, GL_FALSE, view); getuniformslot_shader(shader, &loc, "world"); exts.glUniformMatrix4fv(loc, 1, GL_FALSE, world); getuniformslot_shader(shader, &loc, "invworld"); exts.glUniformMatrix4fv(loc, 1, GL_FALSE, invworld); redraw(); /*create_imagebuffer(&image); load_imagebuffer(image, "texture.tga", imagefile_type_tga); create_texture(&texture); load_texture(texture, image); create_sampler(&sampler); getuniformslot_shader(shader, &loc, "texture"); bind_texture(texture, loc); bind_sampler(sampler, texture);*/ return 0; }
void draw(GLProgram &s){ font->FaceSize(fontsize); FTBBox textbox= font->BBox(text.c_str()); box.pos = pos; float w = textbox.Upper().X() - textbox.Lower().X()+padding*2.0; float h = textbox.Upper().Y() - textbox.Lower().Y()+ padding*2.0; box.size = Vec2f(w,h); box.draw(s); unbind_shader(); font->FaceSize(fontsize*scale); font->Render(text.c_str(),-1,FTPoint( ((pos.x - camera_x) + padding)*scale + window_width/2, ((pos.y - camera_y) + padding)*scale+ window_height/2)); bind_shader(s); }
void App::update(float delta_time) { if (anim_play) frame_count++; if (!hide_gui) gui(); // autoreload frag shader (every 60 frames) if (shader_filepath && shader_file_autoreload && (frame_count % 60) == 0) { struct stat attr; if (!stat(shader_filepath, &attr)) { // file exists if (attr.st_mtime > shader_file_mtime) { // file has been modified shader_file_mtime = (int)attr.st_mtime; reloadShader(); } } } // update camera (-z: forward, y: up) camera_euler_angles += 2.0f*delta_time * v3(-movement_command.rotate.x, -movement_command.rotate.y, 0.0f); camera_euler_angles.x = fminf(fmaxf(-0.5f*(float)M_PI, camera_euler_angles.x), 0.5f*(float)M_PI); // clamp mat3 rot_x = rotationMatrix(v3(1.0f, 0.0f, 0.0f), camera_euler_angles.x); mat3 rot_y = rotationMatrix(v3(0.0f, 1.0f, 0.0f), camera_euler_angles.y); mat3 rot_z = rotationMatrix(v3(0.0f, 0.0f, 1.0f), camera_euler_angles.z); mat3 rot = rot_y * rot_x * rot_z; camera_location += rot * (8.0f*delta_time*movement_command.move); mat4 view_to_world = translationMatrix(camera_location) * m4(rot); mat4 world_to_view = m4(transpose(rot)) * translationMatrix(-camera_location); // bind textures for (int tsi = 0; tsi < (int)ARRAY_COUNT(texture_slots); tsi++) { glActiveTexture(GL_TEXTURE0+tsi); glBindTexture(texture_slots[tsi].target, texture_slots[tsi].texture); } // draw fullscreen triangle(s) glClearColor(0.2f, 0.21f, 0.22f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); { BindShader bind_shader(shader); if (!compile_error_log) { for (int i = 0; i < uniform_count; i++) { uniforms[i].apply(); } } // apply builtin uniforms u_time = (float)frame_count / 60.0f; glUniform1f(shader.getUniformLocation(u_time_name), u_time); vec2 u_resolution = v2(video.pixel_scale*video.width, video.pixel_scale*video.height); glUniform2fv(shader.getUniformLocation(u_resolution_name), 1, u_resolution.e); glUniformMatrix4fv(shader.getUniformLocation(u_view_to_world_name), 1, GL_FALSE, view_to_world.e); glUniformMatrix4fv(shader.getUniformLocation(u_world_to_view_name), 1, GL_FALSE, world_to_view.e); if (single_triangle_mode) { { BindArrayBuffer bind_array_buffer(single_triangle_vbo); glEnableVertexAttribArray(VAT_POSITION); glVertexAttribPointer(VAT_POSITION, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0); glDrawArrays(GL_TRIANGLES, 0, 3); glDisableVertexAttribArray(VAT_POSITION); } } else { { BindArrayBuffer bind_array_buffer(two_triangles_vbo); glEnableVertexAttribArray(VAT_POSITION); glVertexAttribPointer(VAT_POSITION, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableVertexAttribArray(VAT_POSITION); } } } }
void App::update(float delta_time) { if (anim_play) frame_count++; // builtin uniform names static char u_time_name[64] = "u_time"; static char u_resolution_name[64] = "u_resolution"; static char u_view_mat_name[64] = "u_view_mat"; if (ImGui::BeginMainMenuBar()) { if (ImGui::BeginMenu("File")) { if (ImGui::MenuItem("Open fragment shader"/*, "Ctrl+O"*/)) { openShaderDialog(); } if (ImGui::IsItemHovered() && file_path) { ImGui::SetTooltip("%s", file_path); } if (ImGui::MenuItem("Autoreload", nullptr, file_autoreload)) { file_autoreload = !file_autoreload; } ImGui::EndMenu(); } if (ImGui::BeginMenu("Animation")) { if (ImGui::MenuItem(anim_play ? "Pause" : "Play")) { anim_play = !anim_play; } if (ImGui::MenuItem("Reset")) { frame_count = 0; } ImGui::EndMenu(); } if (ImGui::BeginMenu("Window")) { if (ImGui::MenuItem("Uniforms", nullptr, show_uniforms_window)) { show_uniforms_window = !show_uniforms_window; } if (ImGui::MenuItem("Textures", nullptr, show_textures_window)) { show_textures_window = !show_textures_window; } ImGui::EndMenu(); } ImGui::EndMainMenuBar(); } if (show_uniforms_window) { if (ImGui::Begin("Uniforms", &show_uniforms_window)) { if (ImGui::CollapsingHeader("Built-in uniform names")) { ImGui::InputText("Time", u_time_name, sizeof(u_time_name)); ImGui::InputText("Resolution", u_resolution_name, sizeof(u_resolution_name)); ImGui::InputText("View Matrix", u_view_mat_name, sizeof(u_view_mat_name)); } ImGui::Separator(); if (!compile_error_log) { ImGui::AlignFirstTextHeightToWidgets(); ImGui::Text("Data"); ImGui::SameLine(); if (ImGui::Button("Clear")) { if (uniform_data) { memset(uniform_data, 0, uniform_data_size); } } ImGui::SameLine(); if (ImGui::Button("Save")) { writeUniformData(); } ImGui::SameLine(); if (ImGui::Button("Load")) { readUniformData(); } for (int i = 0; i < uniform_count; i++) { // skip builtin uniforms if (!strcmp(u_time_name, uniforms[i].name)) continue; if (!strcmp(u_resolution_name, uniforms[i].name)) continue; if (!strcmp(u_view_mat_name, uniforms[i].name)) continue; uniforms[i].gui(); } } } ImGui::End(); } if (show_textures_window) { if (ImGui::Begin("Textures", &show_textures_window, ImGuiWindowFlags_NoResize|ImGuiWindowFlags_AlwaysAutoResize)) { ImGui::Columns(2); for (int tsi = 0; tsi < ARRAY_COUNT(texture_slots); tsi++) { TextureSlot *texture_slot = texture_slots+tsi; ImGui::BeginGroup(); ImGui::PushID(tsi); ImGui::Text("%d:", tsi); ImGui::SameLine(); ImGui::PushStyleColor(ImGuiCol_Button, ImColor::HSV(0.0f, 0.6f, 0.6f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImColor::HSV(0.0f, 0.7f, 0.7f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImColor::HSV(0.0f, 0.8f, 0.8f)); if (ImGui::SmallButton("x")) texture_slot->clear(); ImGui::PopStyleColor(3); if (ImGui::Button(" 2D ")) openImageDialog(texture_slot); if (ImGui::Button("Cube")) openImageDialog(texture_slot, /*load_cube_cross*/true); ImGui::PopID(); ImGui::EndGroup(); ImGui::SameLine(); //ImTextureID im_tex_id = (ImTextureID)(intptr_t)texture_slot->texture; ImGui::Image((void*)texture_slot, ImVec2(64, 64)); if (ImGui::IsItemHovered() && texture_slot->image_file_path) { ImGui::SetTooltip("%s\n%dx%d", texture_slot->image_file_path, texture_slot->image_width, texture_slot->image_height); } if ((tsi&1) && tsi+1 != ARRAY_COUNT(texture_slots)) { ImGui::Separator(); } else { ImGui::SameLine(); ImGui::Spacing(); } ImGui::NextColumn(); } ImGui::Columns(1); } ImGui::End(); } //ImGui::ShowTestWindow(); // autoreload (every 60 frames) if (file_path && file_autoreload && (frame_count % 60) == 0) { struct stat attr; if (!stat(file_path, &attr)) { // file exists if (attr.st_mtime > file_mod_time) { // file has been modified file_mod_time = attr.st_mtime; loadShader(file_path, /*initial*/false); } } } // overlay messages int overlay_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings; if (!file_path) { ImGui::SetNextWindowPosCenter(); ImGui::Begin("Overlay", nullptr, ImVec2(0, 0), 0.3f, overlay_flags); ImGui::AlignFirstTextHeightToWidgets(); // valign text to button ImGui::Text("No fragment shader"); ImGui::SameLine(); if (ImGui::Button("Open")) { openShaderDialog(); } ImGui::End(); } else if (compile_error_log) { ImGui::SetNextWindowPosCenter(); ImGui::Begin("Overlay", nullptr, ImVec2(0, 0), 0.3f, overlay_flags); ImGui::TextUnformatted(compile_error_log); ImGui::End(); } // update camera camera.euler_angles += 2.0f*delta_time * v3(movement_command.rotate.x, movement_command.rotate.y, 0.0f); mat3 rot_y = rotationMatrix(v3(0.0f, 0.0f, 1.0f), -camera.euler_angles.y); camera.location += rot_y * (8.0f*delta_time*movement_command.move); camera.updateViewMatrix(); // bind textures for (int tsi = 0; tsi < ARRAY_COUNT(texture_slots); tsi++) { glActiveTexture(GL_TEXTURE0+tsi); glBindTexture(texture_slots[tsi].target, texture_slots[tsi].texture); } // draw two triangles glClearColor(0.2, 0.21, 0.22, 1.0); glClear(GL_COLOR_BUFFER_BIT); { BindShader bind_shader(shader); if (!compile_error_log) { for (int i = 0; i < uniform_count; i++) { uniforms[i].apply(); } } // apply builtin uniforms u_time = (float)frame_count / 60.0f; glUniform1f(shader.getUniformLocation(u_time_name), u_time); vec2 u_resolution = v2(video.pixel_scale*video.width, video.pixel_scale*video.height); glUniform2fv(shader.getUniformLocation(u_resolution_name), 1, u_resolution.e); mat4 u_inv_view_mat = camera.makeInverseViewMatrix(); int u_view_mat_loc = shader.getUniformLocation(u_view_mat_name); glUniformMatrix4fv(u_view_mat_loc, 1, GL_FALSE, u_inv_view_mat.e); { BindArrayBuffer bind_array_buffer(two_triangles_vbo); glEnableVertexAttribArray(VAT_POSITION); glVertexAttribPointer(VAT_POSITION, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableVertexAttribArray(VAT_POSITION); } } }
void GLProgram::uniform(const char * name, unsigned int f1, unsigned int f2, unsigned int f3, unsigned int f4){ bind_shader(*this); glUniform4ui(uform_loc(name),f1,f2,f3,f4); }
void GLProgram::uniform(const char * name, unsigned int f){ bind_shader(*this); glUniform1ui(uform_loc(name),f); }
void GLProgram::uniform(const char * name, int f1, int f2, int f3){ bind_shader(*this); glUniform3i(uform_loc(name),f1,f2,f3); }
void GLProgram::uniformf(const char * name, float f1, float f2, float f3, float f4){ bind_shader(*this); glUniform4f(uform_loc(name),f1,f2,f3,f4); }
void GLProgram::uniformf(const char * name, float f){ bind_shader(*this); glUniform1f(uform_loc(name),f); }