void bind(GLenum face) { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer.get_handle()); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, face, cubeMapHandle, 0); glDrawBuffer(GL_COLOR_ATTACHMENT0); gl_check_error(__FILE__, __LINE__); }
void on_draw() override { glfwMakeContextCurrent(window); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); int width, height; glfwGetWindowSize(window, &width, &height); glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(0.1f, 0.1f, 0.5f, 1.0f); const auto proj = camera.get_projection_matrix((float) width / (float) height); const float4x4 view = camera.get_view_matrix(); const float4x4 viewProj = mul(proj, view); skydome.render(viewProj, camera.get_eye_point(), camera.farClip); grid.render(proj, view); gl_check_error(__FILE__, __LINE__); glfwSwapBuffers(window); frameCount++; }
// Bind texture, preserve previous texture state bool GnashTexture::bind() { TextureState * const ts = &_texture_state; ts->old_texture = 0; ts->was_bound = 0; ts->was_enabled = glIsEnabled(GL_TEXTURE_2D); if (!ts->was_enabled) glEnable(GL_TEXTURE_2D); else if (gl_get_param(GL_TEXTURE_BINDING_2D, &ts->old_texture)) ts->was_bound = _texture == ts->old_texture; else return false; if (!ts->was_bound) { gl_purge_errors(); glBindTexture(GL_TEXTURE_2D, _texture); if (gl_check_error()) return false; } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); return true; }
/** the main engine loop. the loop invokes fps counting, SDL event handling, view translation, and calling the main draw_method. */ void loop() { running = true; SDL_Event e; while (running) { fpscounter->frame(); while (SDL_PollEvent(&e)) { //call the input callback methods for(auto cb: callbacks::on_input) { if (!cb(&e)) { break; }; } } //call engine tick callback methods for(auto cb: callbacks::on_engine_tick) { cb(); } //clear the framebuffer to black //in the future, we might disable it for lazy drawing glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); glPushMatrix(); { //set the framebuffer up for camgame rendering glTranslatef(camgame_window.x, camgame_window.y, 0); //invoke all game drawing callback methods for(auto cb: callbacks::on_drawgame) { if (!cb()) { break; }; } } glPopMatrix(); glPushMatrix(); { //the hud coordinate system is automatically established //invoke all hud drawing callback methods for(auto cb: callbacks::on_drawhud) { if (!cb()) { break; }; } } glPopMatrix(); gl_check_error(); //the rendering is done //swap the drawing buffers to actually show the frame SDL_GL_SwapWindow(window); } }
// Release texture, restore previous texture state void GnashTexture::release() { TextureState * const ts = &_texture_state; if (!ts->was_bound && ts->old_texture) glBindTexture(GL_TEXTURE_2D, ts->old_texture); if (!ts->was_enabled) glDisable(GL_TEXTURE_2D); gl_check_error(); }
ExperimentalApp() : GLFWApp(600, 600, "Nearly Empty App") { int width, height; glfwGetWindowSize(window, &width, &height); glViewport(0, 0, width, height); grid = RenderableGrid(1, 100, 100); gl_check_error(__FILE__, __LINE__); camera.look_at({0, 2.5, -2.5}, {0, 2.0, 0}); }
ExperimentalApp() : GLFWApp(940, 720, "GlCamera Sandbox App") { int width, height; glfwGetWindowSize(window, &width, &height); glViewport(0, 0, width, height); cameraController.set_camera(&camera); camera.look_at({0, 8, 24}, {0, 0, 0}); cameraZ = camera.pose.position.z; simpleShader.reset(new GlShader(read_file_text("assets/shaders/simple_vert.glsl"), read_file_text("assets/shaders/simple_frag.glsl"))); { lights.resize(2); lights[0].color = float3(249.f / 255.f, 228.f / 255.f, 157.f / 255.f); lights[0].pose.position = float3(25, 15, 0); lights[1].color = float3(255.f / 255.f, 242.f / 255.f, 254.f / 255.f); lights[1].pose.position = float3(-25, 15, 0); } { cameraPositions.resize(2); cameraPositions[0] = Renderable(make_frustum()); cameraPositions[0].pose.position = float3(0, 8, +24); cameraPositions[0].mesh.set_non_indexed(GL_LINES); cameraPositions[1] = Renderable(make_frustum()); cameraPositions[1].pose.position = float3(0, 8, -24); cameraPositions[1].mesh.set_non_indexed(GL_LINES); } { proceduralModels.resize(4); proceduralModels[0] = Renderable(make_sphere(1.0)); proceduralModels[0].pose.position = float3(0, 2, +8); proceduralModels[1] = Renderable(make_cube()); proceduralModels[1].pose.position = float3(0, 2, -8); proceduralModels[2] = Renderable(make_icosahedron()); proceduralModels[2].pose.position = float3(8, 2, 0); proceduralModels[3] = Renderable(make_octohedron()); proceduralModels[3].pose.position = float3(-8, 2, 0); } start = look_at_pose(float3(0, 8, +24), float3(-8, 2, 0)); end = look_at_pose(float3(0, 8, -24), float3(-8, 2, 0)); grid = RenderableGrid(1, 64, 64); gl_check_error(__FILE__, __LINE__); }
/// Release texture, restore previous texture state static void unbind_texture(TextureState *ts) { if (!ts->was_bound && ts->old_texture) { glBindTexture(ts->target, ts->old_texture); } if (!ts->was_enabled) { glDisable(ts->target); } gl_check_error(); }
// glGetIntegerv() wrapper static bool gl_get_param(GLenum param, unsigned int *pval) { GLint val; gl_purge_errors(); glGetIntegerv(param, &val); if (gl_check_error()) return false; if (pval) *pval = val; return true; }
void create(float2 resolution) { depthBuffer.load_data(resolution.x, resolution.y, GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); framebuffer.attach(GL_DEPTH_ATTACHMENT, depthBuffer); if (!framebuffer.check_complete()) throw std::runtime_error("incomplete framebuffer"); glGenTextures(1, &cubeMapHandle); glBindTexture(GL_TEXTURE_CUBE_MAP, cubeMapHandle); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); for (int i = 0; i < 6; ++i) { glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_R16F, resolution.x, resolution.y, 0, GL_RED, GL_UNSIGNED_SHORT, nullptr); } glBindTexture(GL_TEXTURE_CUBE_MAP, 0); struct CameraInfo { float3 position; float3 target; float3 up; CameraInfo(float3 p, float3 t, float3 u) : position(p), target(t), up(u) {} }; std::vector<CameraInfo> info = { {{0, 0, 0}, { 1, 0, 0}, {0, -1, 0}}, {{0, 0, 0}, {-1, 0, 0}, {0, -1, 0}}, {{0, 0, 0}, { 0, 1, 0}, {0, 0, 1}}, {{0, 0, 0}, { 0, -1, 0}, {0, 0, -1}}, {{0, 0, 0}, { 0, 0, 1}, {0, -1, 0}}, {{0, 0, 0}, { 0, 0, -1}, {0, -1, 0}}, }; for (int i = 0; i < 6; ++i) { CubemapCamera cc; cc.face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i; cc.faceCamera.look_at(info[i].position, info[i].target, info[i].up); faces.push_back(cc); } gl_check_error(__FILE__, __LINE__); }
/** * gl_get_texture_param: * @target: the target to which the texture is bound * @param: the parameter name * @pval: return location for the value * * This function is a wrapper around glGetTexLevelParameteriv() that * does extra error checking. * * Return value: %TRUE on success */ gboolean gl_get_texture_param(GLenum target, GLenum param, guint *pval) { GLint val; gl_purge_errors(); glGetTexLevelParameteriv(target, 0, param, &val); if (gl_check_error()) return FALSE; if (pval) *pval = val; return TRUE; }
/** * gl_get_param: * @param: the parameter name * @pval: return location for the value * * This function is a wrapper around glGetIntegerv() that does extra * error checking. * * Return value: %TRUE on success */ gboolean gl_get_param(GLenum param, guint *pval) { GLint val; gl_purge_errors(); glGetIntegerv(param, &val); if (gl_check_error()) return FALSE; if (pval) *pval = val; return TRUE; }
ExperimentalApp() : GLFWApp(1280, 800, "Glass Material App") { igm.reset(new gui::ImGuiManager(window)); gui::make_dark_theme(); //cubeTex = load_cubemap(); int width, height; glfwGetWindowSize(window, &width, &height); glViewport(0, 0, width, height); // Debugging views for offscreen surfaces uiSurface.bounds = {0, 0, (float) width, (float) height}; uiSurface.add_child( {{0.0000f, +10},{0, +10},{0.1667f, -10},{0.133f, +10}}); uiSurface.add_child( {{0.1667f, +10},{0, +10},{0.3334f, -10},{0.133f, +10}}); uiSurface.layout(); grid = RenderableGrid(1, 100, 100); cameraController.set_camera(&camera); camera.look_at({0, 2.5, -2.5}, {0, 2.0, 0}); lights[0] = {{0, 10, -10}, {0, 0, 1}}; lights[1] = {{0, 10, 10}, {0, 1, 0}}; Renderable reflectiveSphere = Renderable(make_sphere(2.f)); reflectiveSphere.pose = Pose(float4(0, 0, 0, 1), float3(0, 2, 0)); glassModels.push_back(std::move(reflectiveSphere)); Renderable debugAxis = Renderable(make_axis(), false, GL_LINES); debugAxis.pose = Pose(float4(0, 0, 0, 1), float3(0, 1, 0)); regularModels.push_back(std::move(debugAxis)); Renderable cubeA = Renderable(make_cube()); cubeA.pose = Pose(make_rotation_quat_axis_angle({1, 0, 1}, ANVIL_PI / 3), float3(5, 0, 0)); regularModels.push_back(std::move(cubeA)); Renderable cubeB = Renderable(make_cube()); cubeB.pose = Pose(make_rotation_quat_axis_angle({1, 0, 1}, ANVIL_PI / 4), float3(-5, 0, 0)); regularModels.push_back(std::move(cubeB)); glassMaterialShader = make_watched_shader(shaderMonitor, "assets/shaders/glass_vert.glsl", "assets/shaders/glass_frag.glsl"); simpleShader = make_watched_shader(shaderMonitor, "assets/shaders/simple_vert.glsl", "assets/shaders/simple_frag.glsl"); cubeCamera.reset(new CubemapCamera({1024, 1024})); gl_check_error(__FILE__, __LINE__); }
/// Bind texture, preserve previous texture state static bool bind_texture(TextureState *ts, GLenum target, GLuint texture) { ts->target = target; ts->old_texture = 0; ts->was_bound = 0; ts->was_enabled = glIsEnabled(target); GLenum texture_binding; switch (target) { case GL_TEXTURE_1D: texture_binding = GL_TEXTURE_BINDING_1D; break; case GL_TEXTURE_2D: texture_binding = GL_TEXTURE_BINDING_2D; break; case GL_TEXTURE_3D: texture_binding = GL_TEXTURE_BINDING_3D; break; case GL_TEXTURE_RECTANGLE_ARB: texture_binding = GL_TEXTURE_BINDING_RECTANGLE_ARB; break; default: assert(!target); return false; } if (!ts->was_enabled) { glEnable(target); } else if (gl_get_param(texture_binding, &ts->old_texture)) { ts->was_bound = texture == ts->old_texture; } else { return false; } if (!ts->was_bound) { gl_purge_errors(); glBindTexture(target, texture); if (gl_check_error()) { return false; } } return true; }
static gboolean gl_fbo_test_framebuffer( ) { gboolean result = TRUE; glGetError(); /* Clear error state just in case */ render_buffer_t buffer = gl_fbo_create_render_buffer( 640, 480, 0 ); gl_fbo_set_render_target(buffer); GLint status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if( status != GL_FRAMEBUFFER_COMPLETE ) { ERROR( "Framebuffer failure: %x", status ); result = FALSE; } if( result ) { result = gl_check_error( "Setting up framebuffer" ); } gl_fbo_destroy_render_buffer( buffer ); return result; }
GLuint glsl_compile_link(const char *vprogram, const char *fprogram) { char log[32768]; GLuint vhandle, fhandle; GLuint phandle; phandle = glCreateProgram(); vhandle = glCreateShader(GL_VERTEX_SHADER); fhandle = glCreateShader(GL_FRAGMENT_SHADER); /* compile */ /* fragmemt */ glShaderSource(fhandle, 1, &fprogram, NULL); glCompileShader(fhandle); /* Print compile log */ glGetShaderInfoLog(fhandle,32768,NULL,log); printf("Compile Log: %s\n", log); /* vertex */ glShaderSource(vhandle, 1, &vprogram, NULL); glCompileShader(vhandle); /* Print compile log */ glGetShaderInfoLog(vhandle,32768,NULL,log); printf("Compile Log: %s\n", log); /* attach and link */ glAttachShader(phandle, vhandle); glAttachShader(phandle, fhandle); glLinkProgram(phandle); printf("Program compilation/link status: "); gl_check_error(); glGetProgramInfoLog(phandle, 32768, NULL, (GLchar*)log); if ( strlen(log) > 0 ) printf("Link Log: %s\n", log); // mark shaders for deletion when program is deleted glDeleteShader(vhandle); glDeleteShader(fhandle); return phandle; }
void on_draw() override { glfwMakeContextCurrent(window); if (igm) igm->begin_frame(); int width, height; glfwGetWindowSize(window, &width, &height); glViewport(0, 0, width, height); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glDepthMask(GL_TRUE); float windowAspectRatio = (float) width / (float) height; const auto proj = camera.get_projection_matrix(windowAspectRatio); const float4x4 view = camera.get_view_matrix(); const float4x4 viewProj = mul(proj, view); glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); skydome.render(viewProj, camera.get_eye_point(), camera.farClip); float3 target = camera.pose.position; //////////////////////////////////////////// // Directional Light Shadowmap Pass (sun) // //////////////////////////////////////////// { shadowFramebuffer.bind_to_draw(); shadowmapShader->bind(); glClear(GL_DEPTH_BUFFER_BIT); glViewport(0, 0, shadowmapResolution, shadowmapResolution); shadowmapShader->uniform("u_lightViewProj", sunLight->get_view_proj_matrix(target)); for (auto & object : sceneObjects) { if (object->castsShadow) { shadowmapShader->uniform("u_modelMatrix", object->get_model()); object->draw(); } } shadowmapShader->unbind(); shadowFramebuffer.unbind(); } /////////////////////////////// // Spot Light Shadowmap Pass // /////////////////////////////// { for (int i = 0; i < spotLightFramebuffers.size(); ++i) { spotLightFramebuffers[i]->shadowFramebuffer.bind_to_draw(); shadowmapShader->bind(); glClear(GL_DEPTH_BUFFER_BIT); glViewport(0, 0, shadowmapResolution, shadowmapResolution); shadowmapShader->uniform("u_lightViewProj", spotLights[0]->get_view_proj_matrix()); // only take the first into account for debugging for (auto & object : sceneObjects) { if (object->castsShadow) { shadowmapShader->uniform("u_modelMatrix", object->get_model()); object->draw(); } } shadowmapShader->unbind(); spotLightFramebuffers[i]->shadowFramebuffer.unbind(); } } //////////////////////////////// // Point Light Shadowmap Pass // //////////////////////////////// { glViewport(0, 0, shadowmapResolution, shadowmapResolution); for (int i = 0; i < 6; ++i) { pointLightFramebuffer->bind(pointLightFramebuffer->faces[i].face); pointLightShader->bind(); glClear(GL_DEPTH_BUFFER_BIT); pointLightFramebuffer->faces[i].faceCamera.set_position(pointLight->position); // set position from light data to camera for shadow fbo auto viewProj = mul(pointLightFramebuffer->get_projection(), pointLightFramebuffer->faces[i].faceCamera.get_view_matrix()); pointLightShader->uniform("u_lightWorldPosition", pointLight->position); pointLightShader->uniform("u_lightViewProj", viewProj); for (auto & object : sceneObjects) { if (object->castsShadow) { pointLightShader->uniform("u_modelMatrix", object->get_model()); object->draw(); } } pointLightShader->unbind(); pointLightFramebuffer->unbind(); } } // Blur applied to the directional light shadowmap only (others later) { shadowBlurFramebuffer.bind_to_draw(); glDrawBuffer(GL_COLOR_ATTACHMENT0); gaussianBlurShader->bind(); // Configured for a 7x7 gaussianBlurShader->uniform("blurSize", 1.0f / shadowmapResolution); gaussianBlurShader->uniform("sigma", blurSigma); gaussianBlurShader->uniform("u_modelViewProj", Identity4x4); // Horizontal gaussianBlurShader->texture("s_blurTexure", 0, shadowDepthTexture); gaussianBlurShader->uniform("numBlurPixelsPerSide", 3.0f); gaussianBlurShader->uniform("blurMultiplyVec", float2(1.0f, 0.0f)); fullscreen_post_quad.draw_elements(); // Vertical gaussianBlurShader->texture("s_blurTexure", 0, shadowBlurTexture); gaussianBlurShader->uniform("numBlurPixelsPerSide", 3.0f); gaussianBlurShader->uniform("blurMultiplyVec", float2(0.0f, 1.0f)); fullscreen_post_quad.draw_elements(); gaussianBlurShader->unbind(); shadowBlurFramebuffer.unbind(); } { glViewport(0, 0, width, height); sceneShader->bind(); sceneShader->uniform("u_viewProj", viewProj); sceneShader->uniform("u_eye", camera.get_eye_point()); sceneShader->uniform("u_directionalLight.color", sunLight->color); sceneShader->uniform("u_directionalLight.direction", sunLight->direction); sceneShader->uniform("u_dirLightViewProjectionMat", sunLight->get_view_proj_matrix(target)); int samplerIndex = 0; sceneShader->uniform("u_shadowMapBias", 0.01f / shadowmapResolution); // fixme sceneShader->uniform("u_shadowMapTexelSize", float2(1.0f / shadowmapResolution)); sceneShader->texture("s_directionalShadowMap", samplerIndex++, shadowBlurTexture); sceneShader->uniform("u_spotLightViewProjectionMat[0]", spotLights[0]->get_view_proj_matrix()); sceneShader->uniform("u_spotLights[0].color", spotLights[0]->color); sceneShader->uniform("u_spotLights[0].direction", spotLights[0]->direction); sceneShader->uniform("u_spotLights[0].position", spotLights[0]->position); sceneShader->uniform("u_spotLights[0].cutoff", spotLights[0]->get_cutoff()); sceneShader->uniform("u_spotLights[0].constantAtten", spotLights[0]->attenuation.x); sceneShader->uniform("u_spotLights[0].linearAtten", spotLights[0]->attenuation.y); sceneShader->uniform("u_spotLights[0].quadraticAtten", spotLights[0]->attenuation.z); sceneShader->uniform("u_pointLights[0].color", pointLight->color); sceneShader->uniform("u_pointLights[0].position", pointLight->position); sceneShader->uniform("u_pointLights[0].constantAtten", pointLight->attenuation.x); sceneShader->uniform("u_pointLights[0].linearAtten", pointLight->attenuation.y); sceneShader->uniform("u_pointLights[0].quadraticAtten", pointLight->attenuation.z); // Update the spotlight 2D sampler for (int i = 0; i < spotLightFramebuffers.size(); ++i) { auto & fbo = spotLightFramebuffers[i]; std::string uniformLocation = "s_spotLightShadowMap[" + std::to_string(i) + "]"; sceneShader->texture(uniformLocation.c_str(), samplerIndex + i, fbo->shadowDepthTexture); } // Update the pointlight cube sampler for (int i = 0; i < 6; i++) sceneShader->texture("s_pointLightCubemap[0]", 2 + i, pointLightFramebuffer->cubeMapHandle, GL_TEXTURE_CUBE_MAP); for (auto & object : sceneObjects) { sceneShader->uniform("u_modelMatrix", object->get_model()); sceneShader->uniform("u_modelMatrixIT", inv(transpose(object->get_model()))); object->draw(); gl_check_error(__FILE__, __LINE__); } sceneShader->unbind(); } { ImGui::Separator(); ImGui::SliderFloat("Near Clip", &camera.nearClip, 0.1f, 2.0f); ImGui::SliderFloat("Far Clip", &camera.farClip, 2.0f, 75.0f); ImGui::DragFloat3("Light Direction", &sunLight->direction[0], 0.1f, -1.0f, 1.0f); ImGui::Separator(); ImGui::SliderFloat("Blur Sigma", &blurSigma, 0.05f, 9.0f); ImGui::Separator(); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } viewA->draw(uiSurface.children[0]->bounds, int2(width, height)); viewB->draw(uiSurface.children[1]->bounds, int2(width, height)); viewC->draw(uiSurface.children[2]->bounds, int2(width, height)); viewD->draw(uiSurface.children[3]->bounds, int2(width, height)); gl_check_error(__FILE__, __LINE__); if (igm) igm->end_frame(); glfwSwapBuffers(window); }
void on_draw() override { glfwMakeContextCurrent(window); if (igm) igm->begin_frame(); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); int width, height; glfwGetWindowSize(window, &width, &height); glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(1.0f, 0.1f, 0.0f, 1.0f); const auto proj = camera.get_projection_matrix((float) width / (float) height); const float4x4 view = camera.get_view_matrix(); const float4x4 viewProj = mul(proj, view); if (ImGui::SliderInt("Sun Theta", &sunPos.x, 0, 90)) skydome.set_sun_position(sunPos.x, sunPos.y); if (ImGui::SliderInt("Sun Phi", &sunPos.y, 0, 360)) skydome.set_sun_position(sunPos.x, sunPos.y); auto draw_cubes = [&](float3 eye, float4x4 vp) { simpleShader->bind(); simpleShader->uniform("u_eye", eye); simpleShader->uniform("u_viewProj", vp); simpleShader->uniform("u_emissive", float3(0, 0, 0)); simpleShader->uniform("u_diffuse", float3(0.33f, 0.33f, 0.33f)); for (int i = 0; i < 2; i++) { simpleShader->uniform("u_lights[" + std::to_string(i) + "].position", lights[i].position); simpleShader->uniform("u_lights[" + std::to_string(i) + "].color", lights[i].color); } for (const auto & model : regularModels) { simpleShader->uniform("u_modelMatrix", model.get_model()); simpleShader->uniform("u_modelMatrixIT", inv(transpose(model.get_model()))); model.draw(); } simpleShader->unbind(); }; // Render/Update cube camera cubeCamera->render = [&](float3 eyePosition, float4x4 viewMatrix, float4x4 projMatrix) { skydome.render(mul(projMatrix, viewMatrix), eyePosition, camera.farClip); draw_cubes(eyePosition, mul(projMatrix, viewMatrix)); }; cubeCamera->update(camera.get_eye_point()); // render from a camera positioned @ {0, 0, 0} glViewport(0, 0, width, height); skydome.render(viewProj, camera.get_eye_point(), camera.farClip); grid.render(proj, view); draw_cubes(camera.get_eye_point(), viewProj); // Glass material { glassMaterialShader->bind(); glassMaterialShader->uniform("u_eye", camera.get_eye_point()); glassMaterialShader->uniform("u_viewProj", viewProj); // Can set from either a pre-loaded cubemap, or one capured from the cubeCamera glassMaterialShader->texture("u_cubemapTex", 0, cubeCamera->get_cubemap_handle(), GL_TEXTURE_CUBE_MAP); // cubeTex.get_gl_handle() for (const auto & model : glassModels) { glassMaterialShader->uniform("u_modelMatrix", model.get_model()); glassMaterialShader->uniform("u_modelMatrixIT", inv(transpose(model.get_model()))); model.draw(); } glassMaterialShader->unbind(); glDisable(GL_BLEND); } gl_check_error(__FILE__, __LINE__); if (igm) igm->end_frame(); glfwSwapBuffers(window); frameCount++; }
static void *gl_glsl_init(void *data, const char *path) { unsigned i; struct shader_program_info shader_prog_info; bool shader_support = false; #ifdef GLSL_DEBUG char *error_string = NULL; #endif config_file_t *conf = NULL; const char *stock_vertex = NULL; const char *stock_fragment = NULL; glsl_shader_data_t *glsl = (glsl_shader_data_t*) calloc(1, sizeof(glsl_shader_data_t)); if (!glsl) return NULL; (void)shader_support; #ifndef HAVE_OPENGLES RARCH_LOG("[GLSL]: Checking GLSL shader support ...\n"); shader_support = glCreateProgram && glUseProgram && glCreateShader && glDeleteShader && glShaderSource && glCompileShader && glAttachShader && glDetachShader && glLinkProgram && glGetUniformLocation && glUniform1i && glUniform1f && glUniform2fv && glUniform4fv && glUniformMatrix4fv && glGetShaderiv && glGetShaderInfoLog && glGetProgramiv && glGetProgramInfoLog && glDeleteProgram && glGetAttachedShaders && glGetAttribLocation && glEnableVertexAttribArray && glDisableVertexAttribArray && glVertexAttribPointer && glGenBuffers && glBufferData && glDeleteBuffers && glBindBuffer; if (!shader_support) { RARCH_ERR("GLSL shaders aren't supported by your OpenGL driver.\n"); goto error; } #endif glsl->shader = (struct video_shader*)calloc(1, sizeof(*glsl->shader)); if (!glsl->shader) goto error; if (!string_is_empty(path)) { bool ret = false; const char *path_ext = path_get_extension(path); if (string_is_equal_fast(path_ext, "glslp", 5)) { conf = config_file_new(path); if (conf) { ret = video_shader_read_conf_cgp(conf, glsl->shader); glsl->shader->modern = true; } } else if (string_is_equal_fast(path_ext, "glsl", 4)) { strlcpy(glsl->shader->pass[0].source.path, path, sizeof(glsl->shader->pass[0].source.path)); glsl->shader->passes = 1; glsl->shader->modern = true; ret = true; } if (!ret) { RARCH_ERR("[GL]: Failed to parse GLSL shader.\n"); goto error; } } else { RARCH_WARN("[GL]: Stock GLSL shaders will be used.\n"); glsl->shader->passes = 1; glsl->shader->pass[0].source.string.vertex = strdup(glsl_core ? stock_vertex_core : stock_vertex_modern); glsl->shader->pass[0].source.string.fragment = strdup(glsl_core ? stock_fragment_core : stock_fragment_modern); glsl->shader->modern = true; } if (!string_is_empty(path)) video_shader_resolve_relative(glsl->shader, path); video_shader_resolve_parameters(conf, glsl->shader); if (conf) { config_file_free(conf); conf = NULL; } stock_vertex = (glsl->shader->modern) ? stock_vertex_modern : stock_vertex_legacy; stock_fragment = (glsl->shader->modern) ? stock_fragment_modern : stock_fragment_legacy; if (glsl_core) { stock_vertex = stock_vertex_core; stock_fragment = stock_fragment_core; } #ifdef HAVE_OPENGLES if (!glsl->shader->modern) { RARCH_ERR("[GL]: GLES context is used, but shader is not modern. Cannot use it.\n"); goto error; } #else if (glsl_core && !glsl->shader->modern) { RARCH_ERR("[GL]: GL core context is used, but shader is not core compatible. Cannot use it.\n"); goto error; } #endif /* Find all aliases we use in our GLSLP and add #defines for them so * that a shader can choose a fallback if we are not using a preset. */ *glsl->alias_define = '\0'; for (i = 0; i < glsl->shader->passes; i++) { if (*glsl->shader->pass[i].alias) { char define[128]; define[0] = '\0'; snprintf(define, sizeof(define), "#define %s_ALIAS\n", glsl->shader->pass[i].alias); strlcat(glsl->alias_define, define, sizeof(glsl->alias_define)); } } shader_prog_info.vertex = stock_vertex; shader_prog_info.fragment = stock_fragment; shader_prog_info.is_file = false; if (!gl_glsl_compile_program(glsl, 0, &glsl->prg[0], &shader_prog_info)) { RARCH_ERR("GLSL stock programs failed to compile.\n"); goto error; } if (!gl_glsl_compile_programs(glsl, &glsl->prg[1])) goto error; if (!gl_load_luts(glsl->shader, glsl->lut_textures)) { RARCH_ERR("[GL]: Failed to load LUTs.\n"); goto error; } for (i = 0; i <= glsl->shader->passes; i++) gl_glsl_find_uniforms(glsl, i, glsl->prg[i].id, &glsl->uniforms[i]); #ifdef GLSL_DEBUG if (!gl_check_error(&error_string)) { RARCH_ERR("%s\n", error_string); free(error_string); RARCH_WARN("Detected GL error in GLSL.\n"); } #endif if (glsl->shader->variables) { retro_ctx_memory_info_t mem_info; struct state_tracker_info info; mem_info.id = RETRO_MEMORY_SYSTEM_RAM; core_get_memory(&mem_info); info.wram = (uint8_t*)mem_info.data; info.info = glsl->shader->variable; info.info_elem = glsl->shader->variables; info.script = NULL; info.script_class = NULL; #ifdef HAVE_PYTHON info.script = glsl->shader->script; if (*glsl->shader->script_class) info.script_class= glsl->shader->script_class; #endif info.script_is_file = NULL; glsl->state_tracker = state_tracker_init(&info); if (!glsl->state_tracker) RARCH_WARN("Failed to init state tracker.\n"); } glsl->prg[glsl->shader->passes + 1] = glsl->prg[0]; glsl->uniforms[glsl->shader->passes + 1] = glsl->uniforms[0]; if (glsl->shader->modern) { shader_prog_info.vertex = glsl_core ? stock_vertex_core_blend : stock_vertex_modern_blend; shader_prog_info.fragment = glsl_core ? stock_fragment_core_blend : stock_fragment_modern_blend; shader_prog_info.is_file = false; gl_glsl_compile_program( glsl, VIDEO_SHADER_STOCK_BLEND, &glsl->prg[VIDEO_SHADER_STOCK_BLEND], &shader_prog_info ); gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_STOCK_BLEND].id, &glsl->uniforms[VIDEO_SHADER_STOCK_BLEND]); } else { glsl->prg[VIDEO_SHADER_STOCK_BLEND] = glsl->prg[0]; glsl->uniforms[VIDEO_SHADER_STOCK_BLEND] = glsl->uniforms[0]; } #ifdef HAVE_SHADERPIPELINE #ifdef HAVE_OPENGLES if (gl_query_extension("GL_OES_standard_derivatives")) { shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_ribbon_modern : stock_vertex_xmb_ribbon_legacy; shader_prog_info.fragment = stock_fragment_xmb; } else { shader_prog_info.vertex = stock_vertex_xmb_ribbon_simple_legacy; shader_prog_info.fragment = stock_fragment_xmb_ribbon_simple; } #else shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_ribbon_modern : stock_vertex_xmb_ribbon_legacy; shader_prog_info.fragment = stock_fragment_xmb; #endif shader_prog_info.is_file = false; gl_glsl_compile_program( glsl, VIDEO_SHADER_MENU, &glsl->prg[VIDEO_SHADER_MENU], &shader_prog_info); gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU].id, &glsl->uniforms[VIDEO_SHADER_MENU]); shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_simple_modern : stock_vertex_xmb_ribbon_simple_legacy; shader_prog_info.fragment = stock_fragment_xmb_ribbon_simple; gl_glsl_compile_program( glsl, VIDEO_SHADER_MENU_2, &glsl->prg[VIDEO_SHADER_MENU_2], &shader_prog_info); gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_2].id, &glsl->uniforms[VIDEO_SHADER_MENU_2]); #if defined(HAVE_OPENGLES) shader_prog_info.vertex = stock_vertex_xmb_snow_modern; #else shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy; #endif shader_prog_info.fragment = stock_fragment_xmb_simple_snow; gl_glsl_compile_program( glsl, VIDEO_SHADER_MENU_3, &glsl->prg[VIDEO_SHADER_MENU_3], &shader_prog_info); gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_3].id, &glsl->uniforms[VIDEO_SHADER_MENU_3]); #if defined(HAVE_OPENGLES) shader_prog_info.vertex = stock_vertex_xmb_snow_modern; #else shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy; #endif shader_prog_info.fragment = stock_fragment_xmb_snow; gl_glsl_compile_program( glsl, VIDEO_SHADER_MENU_4, &glsl->prg[VIDEO_SHADER_MENU_4], &shader_prog_info); gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_4].id, &glsl->uniforms[VIDEO_SHADER_MENU_4]); #if defined(HAVE_OPENGLES) shader_prog_info.vertex = stock_vertex_xmb_snow_modern; #else shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy; #endif shader_prog_info.fragment = stock_fragment_xmb_bokeh; gl_glsl_compile_program( glsl, VIDEO_SHADER_MENU_5, &glsl->prg[VIDEO_SHADER_MENU_5], &shader_prog_info); gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_5].id, &glsl->uniforms[VIDEO_SHADER_MENU_5]); #endif gl_glsl_reset_attrib(glsl); for (i = 0; i < GFX_MAX_SHADERS; i++) { glGenBuffers(1, &glsl->vbo[i].vbo_primary); glGenBuffers(1, &glsl->vbo[i].vbo_secondary); } return glsl; error: gl_glsl_destroy_resources(glsl); if (conf) config_file_free(conf); if (glsl) free(glsl); return NULL; }
bool gl_glsl_init(const char *path) { #if !defined(HAVE_OPENGLES2) && !defined(HAVE_OPENGL_MODERN) && !defined(__APPLE__) // Load shader functions. LOAD_GL_SYM(CreateProgram); LOAD_GL_SYM(UseProgram); LOAD_GL_SYM(CreateShader); LOAD_GL_SYM(DeleteShader); LOAD_GL_SYM(ShaderSource); LOAD_GL_SYM(CompileShader); LOAD_GL_SYM(AttachShader); LOAD_GL_SYM(DetachShader); LOAD_GL_SYM(LinkProgram); LOAD_GL_SYM(GetUniformLocation); LOAD_GL_SYM(Uniform1i); LOAD_GL_SYM(Uniform1f); LOAD_GL_SYM(Uniform2fv); LOAD_GL_SYM(Uniform4fv); LOAD_GL_SYM(UniformMatrix4fv); LOAD_GL_SYM(GetShaderiv); LOAD_GL_SYM(GetShaderInfoLog); LOAD_GL_SYM(GetProgramiv); LOAD_GL_SYM(GetProgramInfoLog); LOAD_GL_SYM(DeleteProgram); LOAD_GL_SYM(GetAttachedShaders); LOAD_GL_SYM(GetAttribLocation); LOAD_GL_SYM(EnableVertexAttribArray); LOAD_GL_SYM(DisableVertexAttribArray); LOAD_GL_SYM(VertexAttribPointer); RARCH_LOG("Checking GLSL shader support ...\n"); bool shader_support = pglCreateProgram && pglUseProgram && pglCreateShader && pglDeleteShader && pglShaderSource && pglCompileShader && pglAttachShader && pglDetachShader && pglLinkProgram && pglGetUniformLocation && pglUniform1i && pglUniform1f && pglUniform2fv && pglUniform4fv && pglUniformMatrix4fv && pglGetShaderiv && pglGetShaderInfoLog && pglGetProgramiv && pglGetProgramInfoLog && pglDeleteProgram && pglGetAttachedShaders && pglGetAttribLocation && pglEnableVertexAttribArray && pglDisableVertexAttribArray && pglVertexAttribPointer; if (!shader_support) { RARCH_ERR("GLSL shaders aren't supported by your OpenGL driver.\n"); return false; } #endif unsigned num_progs = 0; struct shader_program progs[RARCH_GLSL_MAX_SHADERS] = {{0}}; if (path) { num_progs = get_xml_shaders(path, progs, RARCH_GLSL_MAX_SHADERS - 1); if (num_progs == 0) { RARCH_ERR("Couldn't find any valid shaders in XML file.\n"); return false; } } else { RARCH_WARN("[GL]: Stock GLSL shaders will be used.\n"); num_progs = 1; progs[0].vertex = strdup(stock_vertex_modern); progs[0].fragment = strdup(stock_fragment_modern); glsl_modern = true; } #ifdef HAVE_OPENGLES2 if (!glsl_modern) { RARCH_ERR("[GL]: GLES context is used, but shader is not modern. Cannot use it.\n"); return false; } #endif struct shader_program stock_prog = {0}; stock_prog.vertex = strdup(glsl_modern ? stock_vertex_modern : stock_vertex_legacy); stock_prog.fragment = strdup(glsl_modern ? stock_fragment_modern : stock_fragment_legacy); if (!compile_programs(&gl_program[0], &stock_prog, 1)) { RARCH_ERR("GLSL stock programs failed to compile.\n"); return false; } for (unsigned i = 0; i < num_progs; i++) { gl_filter_type[i + 1] = progs[i].filter; gl_scale[i + 1].type_x = progs[i].type_x; gl_scale[i + 1].type_y = progs[i].type_y; gl_scale[i + 1].scale_x = progs[i].scale_x; gl_scale[i + 1].scale_y = progs[i].scale_y; gl_scale[i + 1].abs_x = progs[i].abs_x; gl_scale[i + 1].abs_y = progs[i].abs_y; gl_scale[i + 1].valid = progs[i].valid_scale; } if (!compile_programs(&gl_program[1], progs, num_progs)) return false; // RetroArch custom two-pass with two different files. if (num_progs == 1 && *g_settings.video.second_pass_shader && g_settings.video.render_to_texture) { unsigned secondary_progs = get_xml_shaders(g_settings.video.second_pass_shader, progs, 1); if (secondary_progs == 1) { if (!compile_programs(&gl_program[2], progs, 1)) { RARCH_ERR("Failed to compile second pass shader.\n"); return false; } num_progs++; } else { RARCH_ERR("Did not find exactly one valid shader in secondary shader file.\n"); return false; } } for (unsigned i = 0; i <= num_progs; i++) find_uniforms(gl_program[i], &gl_uniforms[i]); #ifdef GLSL_DEBUG if (!gl_check_error()) RARCH_WARN("Detected GL error in GLSL.\n"); #endif if (gl_tracker_info_cnt > 0) { struct state_tracker_info info = {0}; info.wram = (uint8_t*)pretro_get_memory_data(RETRO_MEMORY_SYSTEM_RAM); info.info = gl_tracker_info; info.info_elem = gl_tracker_info_cnt; #ifdef HAVE_PYTHON info.script = gl_script_program; info.script_class = *gl_tracker_script_class ? gl_tracker_script_class : NULL; info.script_is_file = false; #endif gl_state_tracker = state_tracker_init(&info); if (!gl_state_tracker) RARCH_WARN("Failed to init state tracker.\n"); } glsl_enable = true; gl_num_programs = num_progs; gl_program[gl_num_programs + 1] = gl_program[0]; gl_uniforms[gl_num_programs + 1] = gl_uniforms[0]; gl_glsl_reset_attrib(); return true; }
static void *gl_init(const video_info_t *video, const input_driver_t **input, void **input_data) { #ifdef _WIN32 gfx_set_dwm(); #endif #ifdef RARCH_CONSOLE if (driver.video_data) return driver.video_data; #endif gl_t *gl = (gl_t*)calloc(1, sizeof(gl_t)); if (!gl) return NULL; if (!gfx_ctx_init()) { free(gl); return NULL; } unsigned full_x = 0, full_y = 0; gfx_ctx_get_video_size(&full_x, &full_y); RARCH_LOG("Detecting resolution %ux%u.\n", full_x, full_y); gfx_ctx_set_swap_interval(video->vsync ? 1 : 0, false); unsigned win_width = video->width; unsigned win_height = video->height; if (video->fullscreen && (win_width == 0) && (win_height == 0)) { win_width = full_x; win_height = full_y; } if (!gfx_ctx_set_video_mode(win_width, win_height, g_settings.video.force_16bit ? 15 : 0, video->fullscreen)) { free(gl); return NULL; } #ifndef RARCH_CONSOLE gfx_ctx_update_window_title(true); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); #endif #if (defined(HAVE_XML) || defined(HAVE_CG)) && defined(_WIN32) // Win32 GL lib doesn't have some functions needed for XML shaders. // Need to load dynamically :( if (!load_gl_proc()) { gfx_ctx_destroy(); free(gl); return NULL; } #endif gl->vsync = video->vsync; gl->fullscreen = video->fullscreen; gl->full_x = full_x; gl->full_y = full_y; gl->win_width = win_width; gl->win_height = win_height; RARCH_LOG("GL: Using resolution %ux%u\n", gl->win_width, gl->win_height); #if defined(HAVE_CG_MENU) && defined(RARCH_CONSOLE) RARCH_LOG("Initializing menu shader ...\n"); gl_cg_set_menu_shader(default_paths.menu_shader_file); #endif if (!gl_shader_init()) { RARCH_ERR("Shader init failed.\n"); gfx_ctx_destroy(); free(gl); return NULL; } RARCH_LOG("GL: Loaded %u program(s).\n", gl_shader_num()); #ifdef HAVE_FBO // Set up render to texture. gl_init_fbo(gl, RARCH_SCALE_BASE * video->input_scale, RARCH_SCALE_BASE * video->input_scale); #endif gl->keep_aspect = video->force_aspect; // Apparently need to set viewport for passes when we aren't using FBOs. gl_shader_use(0); gl_set_viewport(gl, gl->win_width, gl->win_height, false, true); gl_shader_use(1); gl_set_viewport(gl, gl->win_width, gl->win_height, false, true); bool force_smooth = false; if (gl_shader_filter_type(1, &force_smooth)) gl->tex_filter = force_smooth ? GL_LINEAR : GL_NEAREST; else gl->tex_filter = video->smooth ? GL_LINEAR : GL_NEAREST; gl->texture_type = RARCH_GL_TEXTURE_TYPE; gl->texture_fmt = video->rgb32 ? RARCH_GL_FORMAT32 : RARCH_GL_FORMAT16; gl->base_size = video->rgb32 ? sizeof(uint32_t) : sizeof(uint16_t); glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glDisable(GL_DITHER); glClearColor(0, 0, 0, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertex_ptr); memcpy(gl->tex_coords, tex_coords, sizeof(tex_coords)); glTexCoordPointer(2, GL_FLOAT, 0, gl->tex_coords); glColorPointer(4, GL_FLOAT, 0, white_color); set_lut_texture_coords(tex_coords); gl->tex_w = RARCH_SCALE_BASE * video->input_scale; gl->tex_h = RARCH_SCALE_BASE * video->input_scale; #ifdef HAVE_OPENGL_TEXREF glGenBuffers(1, &gl->pbo); glBindBuffer(GL_TEXTURE_REFERENCE_BUFFER_SCE, gl->pbo); glBufferData(GL_TEXTURE_REFERENCE_BUFFER_SCE, gl->tex_w * gl->tex_h * gl->base_size * TEXTURES, NULL, GL_STREAM_DRAW); #endif // Empty buffer that we use to clear out the texture with on res change. gl->empty_buf = calloc(gl->tex_w * gl->tex_h, gl->base_size); gl_init_textures(gl); for (unsigned i = 0; i < TEXTURES; i++) { gl->last_width[i] = gl->tex_w; gl->last_height[i] = gl->tex_h; } for (unsigned i = 0; i < TEXTURES; i++) { gl->prev_info[i].tex = gl->texture[(gl->tex_index - (i + 1)) & TEXTURES_MASK]; gl->prev_info[i].input_size[0] = gl->tex_w; gl->prev_info[i].tex_size[0] = gl->tex_w; gl->prev_info[i].input_size[1] = gl->tex_h; gl->prev_info[i].tex_size[1] = gl->tex_h; memcpy(gl->prev_info[i].coord, tex_coords, sizeof(tex_coords)); } gfx_ctx_input_driver(input, input_data); gl_init_font(gl, g_settings.video.font_path, g_settings.video.font_size); if (!gl_check_error()) { gfx_ctx_destroy(); free(gl); return NULL; } return gl; }
static bool gl_glsl_init(void *data, const char *path) { unsigned i; config_file_t *conf = NULL; glsl_shader_data_t *glsl = NULL; const char *stock_vertex = NULL; const char *stock_fragment = NULL; driver_t *driver = driver_get_ptr(); (void)data; glsl = (glsl_shader_data_t*)calloc(1, sizeof(glsl_shader_data_t)); if (!glsl) return false; #ifndef HAVE_OPENGLES2 RARCH_LOG("Checking GLSL shader support ...\n"); bool shader_support = glCreateProgram && glUseProgram && glCreateShader && glDeleteShader && glShaderSource && glCompileShader && glAttachShader && glDetachShader && glLinkProgram && glGetUniformLocation && glUniform1i && glUniform1f && glUniform2fv && glUniform4fv && glUniformMatrix4fv && glGetShaderiv && glGetShaderInfoLog && glGetProgramiv && glGetProgramInfoLog && glDeleteProgram && glGetAttachedShaders && glGetAttribLocation && glEnableVertexAttribArray && glDisableVertexAttribArray && glVertexAttribPointer && glGenBuffers && glBufferData && glDeleteBuffers && glBindBuffer; if (!shader_support) { RARCH_ERR("GLSL shaders aren't supported by your OpenGL driver.\n"); free(glsl); return false; } #endif glsl->shader = (struct video_shader*)calloc(1, sizeof(*glsl->shader)); if (!glsl->shader) { free(glsl); return false; } if (path) { bool ret; const char *path_ext = path_get_extension(path); if (!strcmp(path_ext, "glsl")) { strlcpy(glsl->shader->pass[0].source.path, path, sizeof(glsl->shader->pass[0].source.path)); glsl->shader->passes = 1; glsl->shader->modern = true; ret = true; } else if (!strcmp(path_ext, "glslp")) { conf = config_file_new(path); if (conf) { ret = video_shader_read_conf_cgp(conf, glsl->shader); glsl->shader->modern = true; } else ret = false; } else ret = false; if (!ret) { RARCH_ERR("[GL]: Failed to parse GLSL shader.\n"); free(glsl->shader); free(glsl); return false; } } else { RARCH_WARN("[GL]: Stock GLSL shaders will be used.\n"); glsl->shader->passes = 1; glsl->shader->pass[0].source.string.vertex = strdup(glsl_core ? stock_vertex_core : stock_vertex_modern); glsl->shader->pass[0].source.string.fragment = strdup(glsl_core ? stock_fragment_core : stock_fragment_modern); glsl->shader->modern = true; } video_shader_resolve_relative(glsl->shader, path); video_shader_resolve_parameters(conf, glsl->shader); if (conf) { config_file_free(conf); conf = NULL; } stock_vertex = (glsl->shader->modern) ? stock_vertex_modern : stock_vertex_legacy; stock_fragment = (glsl->shader->modern) ? stock_fragment_modern : stock_fragment_legacy; if (glsl_core) { stock_vertex = stock_vertex_core; stock_fragment = stock_fragment_core; } #ifdef HAVE_OPENGLES2 if (!glsl->shader->modern) { RARCH_ERR("[GL]: GLES context is used, but shader is not modern. Cannot use it.\n"); goto error; } #else if (glsl_core && !glsl->shader->modern) { RARCH_ERR("[GL]: GL core context is used, but shader is not core compatible. Cannot use it.\n"); goto error; } #endif /* Find all aliases we use in our GLSLP and add #defines for them so * that a shader can choose a fallback if we are not using a preset. */ *glsl->glsl_alias_define = '\0'; for (i = 0; i < glsl->shader->passes; i++) { if (*glsl->shader->pass[i].alias) { char define[128] = {0}; snprintf(define, sizeof(define), "#define %s_ALIAS\n", glsl->shader->pass[i].alias); strlcat(glsl->glsl_alias_define, define, sizeof(glsl->glsl_alias_define)); } } if (!(glsl->gl_program[0] = compile_program(glsl, stock_vertex, stock_fragment, 0))) { RARCH_ERR("GLSL stock programs failed to compile.\n"); goto error; } if (!compile_programs(glsl, &glsl->gl_program[1])) goto error; if (!gl_load_luts(glsl->shader, glsl->gl_teximage)) { RARCH_ERR("[GL]: Failed to load LUTs.\n"); goto error; } for (i = 0; i <= glsl->shader->passes; i++) find_uniforms(glsl, i, glsl->gl_program[i], &glsl->gl_uniforms[i]); #ifdef GLSL_DEBUG if (!gl_check_error()) RARCH_WARN("Detected GL error in GLSL.\n"); #endif if (glsl->shader->variables) { struct state_tracker_info info = {0}; info.wram = (uint8_t*)pretro_get_memory_data(RETRO_MEMORY_SYSTEM_RAM); info.info = glsl->shader->variable; info.info_elem = glsl->shader->variables; #ifdef HAVE_PYTHON info.script = glsl->shader->script; info.script_class = *glsl->shader->script_class ? glsl->shader->script_class : NULL; #endif glsl->gl_state_tracker = state_tracker_init(&info); if (!glsl->gl_state_tracker) RARCH_WARN("Failed to init state tracker.\n"); } glsl->gl_program[glsl->shader->passes + 1] = glsl->gl_program[0]; glsl->gl_uniforms[glsl->shader->passes + 1] = glsl->gl_uniforms[0]; if (glsl->shader->modern) { glsl->gl_program[GL_SHADER_STOCK_BLEND] = compile_program( glsl, glsl_core ? stock_vertex_core_blend : stock_vertex_modern_blend, glsl_core ? stock_fragment_core_blend : stock_fragment_modern_blend, GL_SHADER_STOCK_BLEND); find_uniforms(glsl, 0, glsl->gl_program[GL_SHADER_STOCK_BLEND], &glsl->gl_uniforms[GL_SHADER_STOCK_BLEND]); } else { glsl->gl_program [GL_SHADER_STOCK_BLEND] = glsl->gl_program[0]; glsl->gl_uniforms[GL_SHADER_STOCK_BLEND] = glsl->gl_uniforms[0]; } gl_glsl_reset_attrib(glsl); for (i = 0; i < GFX_MAX_SHADERS; i++) { glGenBuffers(1, &glsl->glsl_vbo[i].vbo_primary); glGenBuffers(1, &glsl->glsl_vbo[i].vbo_secondary); } driver->video_shader_data = glsl; return true; error: gl_glsl_destroy_resources(glsl); if (glsl) free(glsl); return false; }
void on_draw() override { glfwMakeContextCurrent(window); if (igm) igm->begin_frame(); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); int width, height; glfwGetWindowSize(window, &width, &height); glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(1.0f, 0.1f, 0.0f, 1.0f); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::SliderFloat("Projectile Velocity", &turret.velocity, 0.f, 100.f); if (ImGui::Button("Fire")) { turret.projectile = BallisticProjectile(); turret.projectile.p = turret.source.pose; turret.projectile.lastPos = turret.source.pose.position; turret.projectile.gravity = 0.0; /* float3 firingSolutionLow; float3 firingSolutionHigh; auto numSolutions = solve_ballistic_arc(turret.source.pose.position, turret.velocity, turret.target.pose.position, 9.8f, firingSolutionLow, firingSolutionHigh); */ float3 fireVelocity; float gravity; auto canFire = solve_ballistic_arc_lateral(turret.source.pose.position, turret.velocity, turret.target.pose.position, 10.f, fireVelocity, gravity); //std::cout << "Num Solutions: " << numSolutions << std::endl; //std::cout << "Low Solution: " << firingSolutionLow << std::endl; std::cout << "Fire Velocity: " << fireVelocity << std::endl; if (canFire) { turret.projectile.gravity = gravity; turret.projectile.add_impulse(fireVelocity); turret.fired = true; } } ImGui::Spacing(); if (ImGui::SliderInt("M", &ssM, 1, 30)) regeneratePointer = true; if (ImGui::SliderInt("N1", &ssN1, 1, 30)) regeneratePointer = true; if (ImGui::SliderInt("N2", &ssN2, 1, 30)) regeneratePointer = true; if (ImGui::SliderInt("N3", &ssN3, 1, 30)) regeneratePointer = true; ImGui::Spacing(); ImGui::BeginGroup(); if (ImGui::SliderFloat3("Position", ¶ms.position.x, -5, 5)) parabolicPointer = make_parabolic_pointer(worldSurface, params); if (ImGui::SliderFloat3("Velocity", ¶ms.velocity.x, -1.f, 1.f)) parabolicPointer = make_parabolic_pointer(worldSurface, params); if (ImGui::SliderFloat("Point Spacing", ¶ms.pointSpacing, 0.5, 2.0)) parabolicPointer = make_parabolic_pointer(worldSurface, params); if (ImGui::SliderFloat("Point Count", ¶ms.pointCount, 16, 64)) parabolicPointer = make_parabolic_pointer(worldSurface, params); ImGui::EndGroup(); const auto proj = camera.get_projection_matrix((float) width / (float) height); const float4x4 view = camera.get_view_matrix(); const float4x4 viewProj = mul(proj, view); glViewport(0, 0, width, height); skydome.render(viewProj, camera.get_eye_point(), camera.farClip); grid.render(proj, view); { simpleShader->bind(); simpleShader->uniform("u_eye", camera.get_eye_point()); simpleShader->uniform("u_viewProj", viewProj); simpleShader->uniform("u_emissive", float3(0, 0, 0)); simpleShader->uniform("u_diffuse", float3(0.0f, 1.0f, 0.0f)); for (int i = 0; i < 2; i++) { simpleShader->uniform("u_lights[" + std::to_string(i) + "].position", lights[i].position); simpleShader->uniform("u_lights[" + std::to_string(i) + "].color", lights[i].color); } for (const auto & model : shadedModels) { simpleShader->uniform("u_modelMatrix", model.get_model()); simpleShader->uniform("u_modelMatrixIT", inv(transpose(model.get_model()))); model.draw(); } { simpleShader->uniform("u_modelMatrix", turret.source.get_model()); simpleShader->uniform("u_modelMatrixIT", inv(transpose(turret.source.get_model()))); turret.source.draw(); simpleShader->uniform("u_modelMatrix", turret.target.get_model()); simpleShader->uniform("u_modelMatrixIT", inv(transpose(turret.target.get_model()))); turret.target.draw(); auto projectileMat = turret.projectile.p.matrix(); simpleShader->uniform("u_modelMatrix", projectileMat); simpleShader->uniform("u_modelMatrixIT", inv(transpose(projectileMat))); turret.bullet.draw(); } simpleShader->unbind(); } { normalDebugShader->bind(); normalDebugShader->uniform("u_viewProj", viewProj); // Some debug models for (const auto & model : debugModels) { normalDebugShader->uniform("u_modelMatrix", model.get_model()); normalDebugShader->uniform("u_modelMatrixIT", inv(transpose(model.get_model()))); model.draw(); } // Supershape { normalDebugShader->uniform("u_modelMatrix", supershape.get_model()); normalDebugShader->uniform("u_modelMatrixIT", inv(transpose(supershape.get_model()))); supershape.draw(); } // Parabolic pointer { normalDebugShader->uniform("u_modelMatrix", parabolicPointer.get_model()); normalDebugShader->uniform("u_modelMatrixIT", inv(transpose(parabolicPointer.get_model()))); parabolicPointer.draw(); } // Parallel transport boxes for (int i = 0; i < ptfBoxes.size(); ++i) { auto & model = ptfBoxes[i]; auto modelMat = ptf[i]; normalDebugShader->uniform("u_modelMatrix", mul(modelMat, make_scaling_matrix(0.01))); normalDebugShader->uniform("u_modelMatrixIT", inv(transpose(modelMat))); model.draw(); } normalDebugShader->unbind(); } gl_check_error(__FILE__, __LINE__); if (igm) igm->end_frame(); glfwSwapBuffers(window); frameCount++; }
int gl_shader_check_error(GLhandleARB obj, GLenum obj_query, GLSLCheckMode m, const char *file, const int line) { GLsizei length; GLcharARB buffer[255]; GLenum glerr; GLint param; int res=0; glerr = gl_check_error(m, file, line); if(!obj) return glerr; if(obj_query != GL_OBJECT_TYPE_ARB && obj_query != GL_OBJECT_DELETE_STATUS_ARB && obj_query != GL_OBJECT_COMPILE_STATUS_ARB && obj_query != GL_OBJECT_LINK_STATUS_ARB && obj_query != GL_OBJECT_VALIDATE_STATUS_ARB ) { osd_printf_warning("%s:%d: GL Error: gl_shader_check_error unsupported object query 0x%X\n", file, line, (unsigned int)obj_query); return -1; } pfn_glGetObjectParameterivARB(obj, obj_query, ¶m); switch(obj_query) { case GL_OBJECT_TYPE_ARB: if( param!=GL_PROGRAM_OBJECT_ARB && param!=GL_SHADER_OBJECT_ARB ) { if ( CHECK_VERBOSE <= m ) osd_printf_warning("%s:%d: GL Error: object type 0x%X generation failed\n", file, line, (unsigned int)(FPTR)obj); res=-1; } else if ( CHECK_ALWAYS_VERBOSE <= m ) { if(param==GL_PROGRAM_OBJECT_ARB) osd_printf_warning("%s:%d: GL Error: object type 0x%X is PROGRAM, successful\n", file, line, (unsigned int)(FPTR)obj); else osd_printf_warning("%s:%d: GL Info: object type 0x%X is SHADER, successful\n", file, line, (unsigned int)(FPTR)obj); } break; case GL_OBJECT_DELETE_STATUS_ARB: if(param!=1) { if ( CHECK_ALWAYS_VERBOSE <= m ) osd_printf_warning("%s:%d: GL Info: object 0x%X not yet marked for deletion\n", file, line, (unsigned int)(FPTR)obj); } else if ( CHECK_ALWAYS_VERBOSE <= m ) { osd_printf_warning("%s:%d: GL Info: object 0x%X deletion successful\n", file, line, (unsigned int)(FPTR)obj); } break; case GL_OBJECT_COMPILE_STATUS_ARB: if(param!=1) { if ( CHECK_VERBOSE <= m ) osd_printf_warning("%s:%d: GL Error: object 0x%X compilation failed\n", file, line, (unsigned int)(FPTR)obj); res=-1; } else if ( CHECK_ALWAYS_VERBOSE <= m ) { osd_printf_warning("%s:%d: GL Info: object 0x%X compiled successful\n", file, line, (unsigned int)(FPTR)obj); } break; case GL_OBJECT_LINK_STATUS_ARB: if(param!=1) { if ( CHECK_VERBOSE <= m ) osd_printf_warning("%s:%d: GL Error: object 0x%X linking failed\n", file, line, (unsigned int)(FPTR)obj); res=-1; } else if ( CHECK_ALWAYS_VERBOSE <= m ) { osd_printf_warning("%s:%d: GL Info: object 0x%X linked successful\n", file, line, (unsigned int)(FPTR)obj); } break; case GL_OBJECT_VALIDATE_STATUS_ARB: if(param!=1) { if ( CHECK_VERBOSE <= m ) osd_printf_warning("%s:%d: GL Error: object 0x%X validation failed\n", file, line, (unsigned int)(FPTR)obj); res=-1; } else if ( CHECK_ALWAYS_VERBOSE <= m ) { osd_printf_warning("%s:%d: GL Info: object 0x%X validation successful\n", file, line, (unsigned int)(FPTR)obj); } break; } if ( res<0 || CHECK_ALWAYS_VERBOSE <= m ) { length=0; pfn_glGetInfoLogARB(obj, sizeof(buffer), &length, buffer); if(length>0) osd_printf_warning("%s:%d glInfoLog: %s\n", file, line, buffer); } (void) glGetError(); // ;-) return res; }
static bool gl_glsl_init(void *data, const char *path) { unsigned i; (void)data; #ifndef HAVE_OPENGLES2 RARCH_LOG("Checking GLSL shader support ...\n"); bool shader_support = glCreateProgram && glUseProgram && glCreateShader && glDeleteShader && glShaderSource && glCompileShader && glAttachShader && glDetachShader && glLinkProgram && glGetUniformLocation && glUniform1i && glUniform1f && glUniform2fv && glUniform4fv && glUniformMatrix4fv && glGetShaderiv && glGetShaderInfoLog && glGetProgramiv && glGetProgramInfoLog && glDeleteProgram && glGetAttachedShaders && glGetAttribLocation && glEnableVertexAttribArray && glDisableVertexAttribArray && glVertexAttribPointer && glGenBuffers && glBufferData && glDeleteBuffers && glBindBuffer; if (!shader_support) { RARCH_ERR("GLSL shaders aren't supported by your OpenGL driver.\n"); return false; } #endif glsl_shader = (struct gfx_shader*)calloc(1, sizeof(*glsl_shader)); if (!glsl_shader) return false; if (path) { bool ret; if (strcmp(path_get_extension(path), "glsl") == 0) { strlcpy(glsl_shader->pass[0].source.cg, path, sizeof(glsl_shader->pass[0].source.cg)); glsl_shader->passes = 1; glsl_shader->modern = true; ret = true; } else if (strcmp(path_get_extension(path), "glslp") == 0) { config_file_t *conf = config_file_new(path); if (conf) { ret = gfx_shader_read_conf_cgp(conf, glsl_shader); glsl_shader->modern = true; config_file_free(conf); } else ret = false; } else ret = gfx_shader_read_xml(path, glsl_shader); if (!ret) { RARCH_ERR("[GL]: Failed to parse GLSL shader.\n"); return false; } } else { RARCH_WARN("[GL]: Stock GLSL shaders will be used.\n"); glsl_shader->passes = 1; glsl_shader->pass[0].source.xml.vertex = strdup(glsl_core ? stock_vertex_core : stock_vertex_modern); glsl_shader->pass[0].source.xml.fragment = strdup(glsl_core ? stock_fragment_core : stock_fragment_modern); glsl_shader->modern = true; } gfx_shader_resolve_relative(glsl_shader, path); const char *stock_vertex = glsl_shader->modern ? stock_vertex_modern : stock_vertex_legacy; const char *stock_fragment = glsl_shader->modern ? stock_fragment_modern : stock_fragment_legacy; if (glsl_core) { stock_vertex = stock_vertex_core; stock_fragment = stock_fragment_core; } #ifdef HAVE_OPENGLES2 if (!glsl_shader->modern) { RARCH_ERR("[GL]: GLES context is used, but shader is not modern. Cannot use it.\n"); goto error; } #else if (glsl_core && !glsl_shader->modern) { RARCH_ERR("[GL]: GL core context is used, but shader is not core compatible. Cannot use it.\n"); goto error; } #endif if (!(gl_program[0] = compile_program(stock_vertex, stock_fragment, 0))) { RARCH_ERR("GLSL stock programs failed to compile.\n"); goto error; } if (!compile_programs(&gl_program[1])) goto error; if (!gl_load_luts(glsl_shader, gl_teximage)) { RARCH_ERR("[GL]: Failed to load LUTs.\n"); goto error; } for (i = 0; i <= glsl_shader->passes; i++) find_uniforms(i, gl_program[i], &gl_uniforms[i]); #ifdef GLSL_DEBUG if (!gl_check_error()) RARCH_WARN("Detected GL error in GLSL.\n"); #endif if (glsl_shader->variables) { struct state_tracker_info info = {0}; info.wram = (uint8_t*)pretro_get_memory_data(RETRO_MEMORY_SYSTEM_RAM); info.info = glsl_shader->variable; info.info_elem = glsl_shader->variables; #ifdef HAVE_PYTHON info.script = glsl_shader->script; info.script_class = *glsl_shader->script_class ? glsl_shader->script_class : NULL; #endif gl_state_tracker = state_tracker_init(&info); if (!gl_state_tracker) RARCH_WARN("Failed to init state tracker.\n"); } glsl_enable = true; gl_program[glsl_shader->passes + 1] = gl_program[0]; gl_uniforms[glsl_shader->passes + 1] = gl_uniforms[0]; if (glsl_shader->modern) { gl_program[GL_SHADER_STOCK_BLEND] = compile_program(glsl_core ? stock_vertex_core_blend : stock_vertex_modern_blend, glsl_core ? stock_fragment_core_blend : stock_fragment_modern_blend, GL_SHADER_STOCK_BLEND); find_uniforms(0, gl_program[GL_SHADER_STOCK_BLEND], &gl_uniforms[GL_SHADER_STOCK_BLEND]); } else { gl_program[GL_SHADER_STOCK_BLEND] = gl_program[0]; gl_uniforms[GL_SHADER_STOCK_BLEND] = gl_uniforms[0]; } gl_glsl_reset_attrib(); for (i = 0; i < GFX_MAX_SHADERS; i++) { glGenBuffers(1, &glsl_vbo[i].vbo_primary); glGenBuffers(1, &glsl_vbo[i].vbo_secondary); } return true; error: gl_glsl_deinit(); return false; }
ExperimentalApp() : GLFWApp(1280, 800, "Geometric Algorithm Development App") { glfwSwapInterval(0); igm.reset(new gui::ImGuiManager(window)); gui::make_dark_theme(); fixedTimer.start(); lights[0] = {{0, 10, -10}, {0, 0, 1}}; lights[1] = {{0, 10, 10}, {0, 1, 0}}; int width, height; glfwGetWindowSize(window, &width, &height); glViewport(0, 0, width, height); grid = RenderableGrid(1, 100, 100); cameraController.set_camera(&camera); camera.look_at({0, 2.5, -2.5}, {0, 2.0, 0}); simpleShader = make_watched_shader(shaderMonitor, "../assets/shaders/simple_vert.glsl", "assets/shaders/simple_frag.glsl"); normalDebugShader = make_watched_shader(shaderMonitor, "../assets/shaders/normal_debug_vert.glsl", "assets/shaders/normal_debug_frag.glsl"); Renderable debugAxis = Renderable(make_axis(), false, GL_LINES); debugAxis.pose = Pose(float4(0, 0, 0, 1), float3(0, 1, 0)); debugModels.push_back(std::move(debugAxis)); // Initial supershape settings supershape = Renderable(make_supershape_3d(16, 5, 7, 4, 12)); supershape.pose.position = {0, 2, -2}; // Initialize PTF stuff { std::array<float3, 4> controlPoints = {float3(0.0f, 0.0f, 0.0f), float3(0.667f, 0.25f, 0.0f), float3(1.33f, 0.25f, 0.0f), float3(2.0f, 0.0f, 0.0f)}; ptf = make_parallel_transport_frame_bezier(controlPoints, 32); for (int i = 0; i < ptf.size(); ++i) { Renderable p = Renderable(make_cube()); ptfBoxes.push_back(std::move(p)); } } // Initialize Parabolic pointer stuff { // Set up the ground plane used as a nav mesh for the parabolic pointer worldSurface = make_plane(48, 48, 96, 96); for (auto & p : worldSurface.vertices) { float4x4 model = make_rotation_matrix({1, 0, 0}, -ANVIL_PI / 2); p = transform_coord(model, p); } worldSurfaceRenderable = Renderable(worldSurface); parabolicPointer = make_parabolic_pointer(worldSurface, params); } // Initialize objects for ballistic trajectory tests { turret.source = Renderable(make_tetrahedron()); turret.source.pose = Pose({-5, 2, 5}); turret.target = Renderable(make_cube()); turret.target.pose = Pose({0, 0, 40}); turret.bullet = Renderable(make_sphere(1.0f)); } float4x4 tMat = mul(make_translation_matrix({3, 4, 5}), make_rotation_matrix({0, 0, 1}, ANVIL_PI / 2)); auto p = make_pose_from_transform_matrix(tMat); std::cout << tMat << std::endl; std::cout << p << std::endl; gl_check_error(__FILE__, __LINE__); }
static bool gl_glsl_init(const char *path) { #if !defined(HAVE_OPENGLES2) && !defined(HAVE_OPENGL_MODERN) && !defined(__APPLE__) // Load shader functions. LOAD_GL_SYM(CreateProgram); LOAD_GL_SYM(UseProgram); LOAD_GL_SYM(CreateShader); LOAD_GL_SYM(DeleteShader); LOAD_GL_SYM(ShaderSource); LOAD_GL_SYM(CompileShader); LOAD_GL_SYM(AttachShader); LOAD_GL_SYM(DetachShader); LOAD_GL_SYM(LinkProgram); LOAD_GL_SYM(GetUniformLocation); LOAD_GL_SYM(Uniform1i); LOAD_GL_SYM(Uniform1f); LOAD_GL_SYM(Uniform2fv); LOAD_GL_SYM(Uniform4fv); LOAD_GL_SYM(UniformMatrix4fv); LOAD_GL_SYM(GetShaderiv); LOAD_GL_SYM(GetShaderInfoLog); LOAD_GL_SYM(GetProgramiv); LOAD_GL_SYM(GetProgramInfoLog); LOAD_GL_SYM(DeleteProgram); LOAD_GL_SYM(GetAttachedShaders); LOAD_GL_SYM(GetAttribLocation); LOAD_GL_SYM(EnableVertexAttribArray); LOAD_GL_SYM(DisableVertexAttribArray); LOAD_GL_SYM(VertexAttribPointer); RARCH_LOG("Checking GLSL shader support ...\n"); bool shader_support = pglCreateProgram && pglUseProgram && pglCreateShader && pglDeleteShader && pglShaderSource && pglCompileShader && pglAttachShader && pglDetachShader && pglLinkProgram && pglGetUniformLocation && pglUniform1i && pglUniform1f && pglUniform2fv && pglUniform4fv && pglUniformMatrix4fv && pglGetShaderiv && pglGetShaderInfoLog && pglGetProgramiv && pglGetProgramInfoLog && pglDeleteProgram && pglGetAttachedShaders && pglGetAttribLocation && pglEnableVertexAttribArray && pglDisableVertexAttribArray && pglVertexAttribPointer; if (!shader_support) { RARCH_ERR("GLSL shaders aren't supported by your OpenGL driver.\n"); return false; } #endif glsl_shader = (struct gfx_shader*)calloc(1, sizeof(*glsl_shader)); if (!glsl_shader) return false; if (path) { bool ret; if (strcmp(path_get_extension(path), "glsl") == 0) { strlcpy(glsl_shader->pass[0].source.cg, path, sizeof(glsl_shader->pass[0].source.cg)); glsl_shader->passes = 1; glsl_shader->modern = true; ret = true; } else if (strcmp(path_get_extension(path), "glslp") == 0) { config_file_t *conf = config_file_new(path); if (conf) { ret = gfx_shader_read_conf_cgp(conf, glsl_shader); glsl_shader->modern = true; config_file_free(conf); } else ret = false; } else ret = gfx_shader_read_xml(path, glsl_shader); if (!ret) { RARCH_ERR("[GL]: Failed to parse GLSL shader.\n"); return false; } } else { RARCH_WARN("[GL]: Stock GLSL shaders will be used.\n"); glsl_shader->passes = 1; glsl_shader->pass[0].source.xml.vertex = strdup(stock_vertex_modern); glsl_shader->pass[0].source.xml.fragment = strdup(stock_fragment_modern); glsl_shader->modern = true; } gfx_shader_resolve_relative(glsl_shader, path); #ifdef HAVE_OPENGLES2 if (!glsl_shader->modern) { RARCH_ERR("[GL]: GLES context is used, but shader is not modern. Cannot use it.\n"); return false; } #endif const char *stock_vertex = glsl_shader->modern ? stock_vertex_modern : stock_vertex_legacy; const char *stock_fragment = glsl_shader->modern ? stock_fragment_modern : stock_fragment_legacy; if (!(gl_program[0] = compile_program(stock_vertex, stock_fragment, 0))) { RARCH_ERR("GLSL stock programs failed to compile.\n"); gl_glsl_free_shader(); return false; } if (!compile_programs(&gl_program[1])) { gl_glsl_free_shader(); return false; } if (!load_luts()) { RARCH_ERR("[GL]: Failed to load LUTs.\n"); gl_glsl_free_shader(); return false; } for (unsigned i = 0; i <= glsl_shader->passes; i++) find_uniforms(gl_program[i], &gl_uniforms[i]); #ifdef GLSL_DEBUG if (!gl_check_error()) RARCH_WARN("Detected GL error in GLSL.\n"); #endif if (glsl_shader->variables) { struct state_tracker_info info = {0}; info.wram = (uint8_t*)pretro_get_memory_data(RETRO_MEMORY_SYSTEM_RAM); info.info = glsl_shader->variable; info.info_elem = glsl_shader->variables; #ifdef HAVE_PYTHON info.script = glsl_shader->script; info.script_class = *glsl_shader->script_class ? glsl_shader->script_class : NULL; #endif gl_state_tracker = state_tracker_init(&info); if (!gl_state_tracker) RARCH_WARN("Failed to init state tracker.\n"); } glsl_enable = true; gl_program[glsl_shader->passes + 1] = gl_program[0]; gl_uniforms[glsl_shader->passes + 1] = gl_uniforms[0]; if (glsl_shader->modern) { gl_program[GL_SHADER_STOCK_BLEND] = compile_program(stock_vertex_modern_blend, stock_fragment_modern_blend, GL_SHADER_STOCK_BLEND); find_uniforms(gl_program[GL_SHADER_STOCK_BLEND], &gl_uniforms[GL_SHADER_STOCK_BLEND]); } else { gl_program[GL_SHADER_STOCK_BLEND] = gl_program[0]; gl_uniforms[GL_SHADER_STOCK_BLEND] = gl_uniforms[0]; } gl_glsl_reset_attrib(); return true; }
ExperimentalApp() : GLFWApp(1280, 720, "Shadow App") { glfwSwapInterval(0); gen = std::mt19937(rd()); igm.reset(new gui::ImGuiManager(window)); gui::make_dark_theme(); int width, height; glfwGetWindowSize(window, &width, &height); glViewport(0, 0, width, height); cameraController.set_camera(&camera); camera.farClip = 55.f; camera.look_at({0, 0, +15}, {0, 0, 0}); // Debugging views uiSurface.bounds = {0, 0, (float) width, (float) height}; uiSurface.add_child( {{0.0000f, +10},{0, +10},{0.1667f, -10},{0.133f, +10}}); uiSurface.add_child( {{0.1667f, +10},{0, +10},{0.3334f, -10},{0.133f, +10}}); uiSurface.add_child( {{0.3334f, +10},{0, +10},{0.5009f, -10},{0.133f, +10}}); uiSurface.add_child( {{0.5000f, +10},{0, +10},{0.6668f, -10},{0.133f, +10}}); uiSurface.add_child( {{0.6668f, +10},{0, +10},{0.8335f, -10},{0.133f, +10}}); uiSurface.add_child( {{0.8335f, +10},{0, +10},{1.0000f, -10},{0.133f, +10}}); uiSurface.layout(); fullscreen_post_quad = make_fullscreen_quad(); sceneShader = make_watched_shader(shaderMonitor, "assets/shaders/shadow/scene_vert.glsl", "assets/shaders/shadow/scene_frag.glsl"); shadowmapShader = make_watched_shader(shaderMonitor, "assets/shaders/shadow/shadowmap_vert.glsl", "assets/shaders/shadow/shadowmap_frag.glsl"); pointLightShader = make_watched_shader(shaderMonitor, "assets/shaders/shadow/point_light_vert.glsl", "assets/shaders/shadow/point_light_frag.glsl"); gaussianBlurShader = make_watched_shader(shaderMonitor, "assets/shaders/gaussian_blur_vert.glsl", "assets/shaders/gaussian_blur_frag.glsl"); skydome.recompute(2, 10.f, 1.15f); auto lightDir = skydome.get_light_direction(); sunLight = std::make_shared<DirectionalLight>(lightDir, float3(.50f, .75f, .825f), 64.f); // todo spotLightB shadowDepthTexture.load_data(shadowmapResolution, shadowmapResolution, GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); shadowFramebuffer.attach(GL_DEPTH_ATTACHMENT, shadowDepthTexture); if (!shadowFramebuffer.check_complete()) throw std::runtime_error("incomplete shadow framebuffer"); shadowBlurTexture.load_data(shadowmapResolution, shadowmapResolution, GL_R32F, GL_RGBA, GL_FLOAT, nullptr); shadowBlurFramebuffer.attach(GL_COLOR_ATTACHMENT0, shadowBlurTexture); if (!shadowBlurFramebuffer.check_complete()) throw std::runtime_error("incomplete blur framebuffer"); auto spotLightA = std::make_shared<SpotLight>(float3(0.f, 10.f, 0.f), float3(0.f, -1.f, 0.f), float3(0.766f, 0.766f, 0.005f), 30.0f, float3(1.0f, 0.0f, 0.0001f)); spotLights.push_back(spotLightA); // Single spotlight fbo for (int i = 0; i < 1; ++i) { auto buffer = std::make_shared<SpotLightFramebuffer>(); buffer->create(shadowmapResolution); spotLightFramebuffers.push_back(buffer); } // Point light init { pointLight.reset(new PointLight(float3(0.f, 0.f, 0.f), float3(0, 1, 1), float3(1.0f, 0.05f, 0.0002f))); pointLightFramebuffer.reset(new PointLightFramebuffer()); pointLightFramebuffer->create(float2(shadowmapResolution)); pointLightSphere = std::make_shared<Renderable>(make_sphere(0.5f)); sceneObjects.push_back(pointLightSphere); } viewA.reset(new GLTextureView(shadowDepthTexture.get_gl_handle())); viewB.reset(new GLTextureView(shadowBlurTexture.get_gl_handle())); viewC.reset(new GLTextureView(spotLightFramebuffers[0]->shadowDepthTexture.get_gl_handle())); viewD.reset(new GLTextureView(pointLightFramebuffer->depthBuffer.get_gl_handle())); auto lucy = load_geometry_from_ply("assets/models/stanford/lucy.ply"); rescale_geometry(lucy, 8.0f); auto lucyBounds = lucy.compute_bounds(); auto statue = std::make_shared<Renderable>(lucy); statue->pose.position = {0, 0, 0}; //sceneObjects.push_back(statue); auto hollowCube = load_geometry_from_ply("assets/models/geometry/CubeHollowOpen.ply"); for (auto & v : hollowCube.vertices) v *= 0.20f; auto hCube = std::make_shared<Renderable>(hollowCube); hCube->pose.position = float3(0, 0, 0); hCube->pose.orientation = make_rotation_quat_around_x(ANVIL_PI / 2); //sceneObjects.push_back(hCube); auto curvedMesh = make_curved_plane(2, 1, 8, 8); sceneObjects.push_back(std::make_shared<Renderable>(curvedMesh)); //floor = std::make_shared<Renderable>(make_plane(32.f, 32.f, 64, 64), false); //floor->pose.orientation = make_rotation_quat_axis_angle({1, 0, 0}, -ANVIL_PI / 2); //floor->pose.position = {0, lucyBounds.min().y, 0}; //sceneObjects.push_back(floor); gl_check_error(__FILE__, __LINE__); }
void on_draw() override { glfwMakeContextCurrent(window); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); int width, height; glfwGetWindowSize(window, &width, &height); glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(0.1f, 0.1f, 0.5f, 1.0f); const auto proj = camera.get_projection_matrix((float) width / (float) height); const float4x4 view = camera.get_view_matrix(); const float4x4 viewProj = mul(proj, view); skydome.render(viewProj, camera.get_eye_point(), camera.farClip); // Simple Shader { simpleShader->bind(); simpleShader->uniform("u_viewProj", viewProj); simpleShader->uniform("u_eye", camera.get_eye_point()); simpleShader->uniform("u_emissive", float3(.10f, 0.10f, 0.10f)); simpleShader->uniform("u_diffuse", float3(0.4f, 0.4f, 0.4f)); for (int i = 0; i < lights.size(); i++) { auto light = lights[i]; simpleShader->uniform("u_lights[" + std::to_string(i) + "].position", light.pose.position); simpleShader->uniform("u_lights[" + std::to_string(i) + "].color", light.color); } for (const auto & model : proceduralModels) { simpleShader->uniform("u_modelMatrix", model.get_model()); simpleShader->uniform("u_modelMatrixIT", inv(transpose(model.get_model()))); model.draw(); } for (const auto & model : cameraPositions) { simpleShader->uniform("u_modelMatrix", model.get_model()); simpleShader->uniform("u_modelMatrixIT", inv(transpose(model.get_model()))); model.draw(); } gl_check_error(__FILE__, __LINE__); simpleShader->unbind(); } grid.render(proj, view); gl_check_error(__FILE__, __LINE__); glfwSwapBuffers(window); frameCount++; }
static void *gl_init(const video_info_t *video, const input_driver_t **input, void **input_data) { #ifdef _WIN32 gfx_set_dwm(); #endif if (!sdlwrap_init()) return NULL; const SDL_VideoInfo *video_info = SDL_GetVideoInfo(); rarch_assert(video_info); unsigned full_x = video_info->current_w; unsigned full_y = video_info->current_h; RARCH_LOG("Detecting desktop resolution %ux%u.\n", full_x, full_y); sdlwrap_set_swap_interval(video->vsync ? 1 : 0, false); unsigned win_width = video->width; unsigned win_height = video->height; if (video->fullscreen && (win_width == 0) && (win_height == 0)) { win_width = full_x; win_height = full_y; } if (!sdlwrap_set_video_mode(win_width, win_height, g_settings.video.force_16bit ? 15 : 0, video->fullscreen)) return NULL; gfx_window_title_reset(); char buf[128]; if (gfx_window_title(buf, sizeof(buf))) sdlwrap_wm_set_caption(buf); // Remove that ugly mouse :D SDL_ShowCursor(SDL_DISABLE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); #if (defined(HAVE_XML) || defined(HAVE_CG)) && defined(_WIN32) // Win32 GL lib doesn't have some functions needed for XML shaders. // Need to load dynamically :( if (!load_gl_proc()) { sdlwrap_destroy(); return NULL; } #endif gl_t *gl = (gl_t*)calloc(1, sizeof(gl_t)); if (!gl) { sdlwrap_destroy(); return NULL; } gl->vsync = video->vsync; gl->fullscreen = video->fullscreen; gl->full_x = full_x; gl->full_y = full_y; gl->win_width = win_width; gl->win_height = win_height; RARCH_LOG("GL: Using resolution %ux%u\n", gl->win_width, gl->win_height); if (!gl_shader_init()) { RARCH_ERR("Shader init failed.\n"); sdlwrap_destroy(); free(gl); return NULL; } RARCH_LOG("GL: Loaded %u program(s).\n", gl_shader_num()); #ifdef HAVE_FBO // Set up render to texture. gl_init_fbo(gl, RARCH_SCALE_BASE * video->input_scale, RARCH_SCALE_BASE * video->input_scale); #endif gl->keep_aspect = video->force_aspect; // Apparently need to set viewport for passes when we aren't using FBOs. gl_shader_use(0); set_viewport(gl, gl->win_width, gl->win_height, false, true); gl_shader_use(1); set_viewport(gl, gl->win_width, gl->win_height, false, true); bool force_smooth; if (gl_shader_filter_type(1, &force_smooth)) gl->tex_filter = force_smooth ? GL_LINEAR : GL_NEAREST; else gl->tex_filter = video->smooth ? GL_LINEAR : GL_NEAREST; gl->texture_type = GL_BGRA; gl->texture_fmt = video->rgb32 ? GL_UNSIGNED_INT_8_8_8_8_REV : GL_UNSIGNED_SHORT_1_5_5_5_REV; gl->base_size = video->rgb32 ? sizeof(uint32_t) : sizeof(uint16_t); glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glDisable(GL_DITHER); glClearColor(0, 0, 0, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glGenTextures(TEXTURES, gl->texture); for (unsigned i = 0; i < TEXTURES; i++) { glBindTexture(GL_TEXTURE_2D, gl->texture[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl->tex_filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl->tex_filter); } glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertexes_flipped); memcpy(gl->tex_coords, tex_coords, sizeof(tex_coords)); glTexCoordPointer(2, GL_FLOAT, 0, gl->tex_coords); glColorPointer(4, GL_FLOAT, 0, white_color); set_lut_texture_coords(tex_coords); gl->tex_w = RARCH_SCALE_BASE * video->input_scale; gl->tex_h = RARCH_SCALE_BASE * video->input_scale; // Empty buffer that we use to clear out the texture with on res change. gl->empty_buf = calloc(gl->tex_w * gl->tex_h, gl->base_size); for (unsigned i = 0; i < TEXTURES; i++) { glBindTexture(GL_TEXTURE_2D, gl->texture[i]); glPixelStorei(GL_UNPACK_ROW_LENGTH, gl->tex_w); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, gl->tex_w, gl->tex_h, 0, gl->texture_type, gl->texture_fmt, gl->empty_buf ? gl->empty_buf : NULL); } glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]); for (unsigned i = 0; i < TEXTURES; i++) { gl->last_width[i] = gl->tex_w; gl->last_height[i] = gl->tex_h; } for (unsigned i = 0; i < TEXTURES; i++) { gl->prev_info[i].tex = gl->texture[(gl->tex_index - (i + 1)) & TEXTURES_MASK]; gl->prev_info[i].input_size[0] = gl->tex_w; gl->prev_info[i].tex_size[0] = gl->tex_w; gl->prev_info[i].input_size[1] = gl->tex_h; gl->prev_info[i].tex_size[1] = gl->tex_h; memcpy(gl->prev_info[i].coord, tex_coords, sizeof(tex_coords)); } // Hook up SDL input driver to get SDL_QUIT events and RESIZE. sdl_input_t *sdl_input = (sdl_input_t*)input_sdl.init(); if (sdl_input) { *input = &input_sdl; *input_data = sdl_input; } else *input = NULL; gl_init_font(gl, g_settings.video.font_path, g_settings.video.font_size); if (!gl_check_error()) { sdlwrap_destroy(); free(gl); return NULL; } return gl; }