网盘地址:https://pan.baidu.com/s/1bpo4xx6XXMUPiRFp_nWqwA 提取码:5lmj 腾讯微云下载地址:https://share.weiyun.com/CVGckNTd 密码:e58wuq
视频特效人才紧缺、需求量大、薪资高,学习正当时,所以今天给大家讲讲关于热门视频特效技术- OpenGL的相关知识,通过本文章,我将带着大家从0到1手把手实现特效美颜相机,让大家系统性掌握OpenGL 核心技术,从而轻松实现各种酷炫的视频特效、吃透视频特效原理,并积累大量图形学/数学知识,助力大家快速成为视频特效技术抢手人才!
那么,首先,我们先来了解一下,什么是OpenGL? OpenGL(Open Graphics Library)是一个跨平台、跨语言的图形编程接口(API)。它被广泛用于实现2D和3D图形渲染,并且是许多应用程序、游戏和网页浏览器的核心组件。
OpenGL主要功能是什么? OpenGL是一个开放的三维图形软件包,它独立于窗口系统和操作系统,以它为基础开发的应用程序可以十分方便地在各种平台间移植;OpenGL使用简便,效率高。
OpenGL的glclearcolor在Mesa中的实现是_mesa_ClearColor 函数。该函数用于指定颜色缓冲区的清除值,用于设置清除颜色。 void GLAPIENTRY _mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) { GET_CURRENT_CONTEXT(ctx);
ctx->PopAttribState |= GL_COLOR_BUFFER_BIT; ctx->Color.ClearColor.f[0] = red; ctx->Color.ClearColor.f[1] = green; ctx->Color.ClearColor.f[2] = blue; ctx->Color.ClearColor.f[3] = alpha; } 在pom.xml文件中添加Swagger依赖库,这里我们使用的是Swagger2版本,在UI方面,比Swagger1版本要好看很多。 package com.example.emos.wx.config;
import io.swagger.annotations.ApiOperation; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.ApiKey; import springfox.documentation.service.AuthorizationScope; import springfox.documentation.service.SecurityReference; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.service.contexts.SecurityContext; import springfox.documentation.spring.web.plugins.ApiSelectorBuilder; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList; import java.util.List;
@Configuration @EnableSwagger2 public class SwaggerConfig {
@Bean
public Docket createRestApi() {
Docket docket = new Docket(DocumentationType.SWAGGER_2);
// ApiInfoBuilder 用于在Swagger界面上添加各种信息
ApiInfoBuilder builder = new ApiInfoBuilder();
builder.title("EMOS在线办公系统");
ApiInfo apiInfo = builder.build();
docket.apiInfo(apiInfo);
// ApiSelectorBuilder 用来设置哪些类中的方法会生成到REST API中
ApiSelectorBuilder selectorBuilder = docket.select();
selectorBuilder.paths(PathSelectors.any()); //所有包下的类
//使用@ApiOperation的方法会被提取到REST API中
selectorBuilder.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class));
docket = selectorBuilder.build();
/*
* 下面的语句是开启对JWT的支持,当用户用Swagger调用受JWT认证保护的方法,
* 必须要先提交参数(例如令牌)
*/
//存储用户必须提交的参数
List<ApiKey> apikey = new ArrayList();
//规定用户需要输入什么参数
apikey.add(new ApiKey("token", "token", "header"));
docket.securitySchemes(apikey);
//如果用户JWT认证通过,则在Swagger中全局有效
AuthorizationScope scope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] scopeArray = {scope};
//存储令牌和作用域
SecurityReference reference = new SecurityReference("token", scopeArray);
List refList = new ArrayList();
refList.add(reference);
SecurityContext context = SecurityContext.builder().securityReferences(refList).build();
List cxtList = new ArrayList();
cxtList.add(context);
docket.securityContexts(cxtList);
return docket;
}
} 向后端提交数据之前,我们先要做好前端的数据验证,比如说验证激活码必须是6位数字。 let data = { code: code, nickname: nickName, photo: avatarUrl, registerCode: that.registerCode }; that.ajax(that.url.register, 'POST', data, function(resp) { let permission = resp.data.permission; uni.setStorageSync('permission', permission); //跳转到index页面 }); 在CheckinController类中创建createFaceModel()方法 public class CheckinController { @PostMapping("/createFaceModel") @ApiOperation("创建人脸模型") public R createFaceModel(@RequestParam("photo") MultipartFile file, @RequestHeader("token") String token) { int userId = jwtUtil.getUserId(token); if (file==null) { return R.error("没有上传文件"); } String fileName = file.getOriginalFilename().toLowerCase(); String path = imageFolder + "/" + fileName; if (!fileName.endsWith(".jpg")) { return R.error("必须提交JPG格式图片"); } else { try { file.transferTo(Paths.get(path)); checkinService.createFaceModel(userId, path); return R.ok("人脸建模成功"); } catch (IOException e) { log.error(e.getMessage()); throw new EmosException("保存图片错误"); } finally { FileUtil.del(path); } } } } 编写CheckinController.java中的Web方法,查询用户签到的结果。 public class CheckinController { …… @Autowired private UserService userService;
@Autowired
private SystemConstants constants;
@GetMapping("/searchTodayCheckin")
@ApiOperation("查询用户当日签到数据")
public R searchTodayCheckin(@RequestHeader("token") String token) {
int userId = jwtUtil.getUserId(token);
HashMap map = checkinService.searchTodayCheckin(userId);
map.put("attendanceTime", constants.attendanceTime);
map.put("closingTime", constants.closingTime);
long days = checkinService.searchCheckinDays(userId);
map.put("checkinDays", days);
//判断日期是否在用户入职之前
DateTime hiredate = DateUtil.parse(userService.searchUserHiredate(userId));
DateTime startDate = DateUtil.beginOfWeek(DateUtil.date());
if (startDate.isBefore(hiredate)) {
startDate = hiredate;
}
DateTime endDate = DateUtil.endOfWeek(DateUtil.date());
HashMap param = new HashMap();
param.put("startDate", startDate.toString());
param.put("endDate", endDate.toString());
param.put("userId", userId);
ArrayList<HashMap> list = checkinService.searchWeekCheckin(param);
map.put("weekCheckin", list);
return R.ok().put("result", map);
}
} 编写TbUserDao.xml文件中的查询语句
如果你只有一小时的时间学习 OpenGL,并且希望使用 Python,那么你的学习目标应该是理解基本的 OpenGL 概念,同时能够编写一个简单的程序来创建并渲染基本的2D形状@Value("${emos.code}")
private String code;
@Value("${workflow.url}")
private String workflow;
@Value("${emos.recieveNotify}")
private String recieveNotify;
……
private void startMeetingWorkflow(String uuid, int creatorId, String date, String start) {
HashMap info = userDao.searchUserInfo(creatorId); //查询创建者用户信息
JSONObject json = new JSONObject();
json.set("url", recieveNotify);
json.set("uuid", uuid);
json.set("openId", info.get("openId"));
json.set("code",code);
json.set("date",date);
json.set("start",start);
String[] roles = info.get("roles").toString().split(",");
//如果不是总经理创建的会议
if (!ArrayUtil.contains(roles, "总经理")) {
//查询总经理ID和同部门的经理的ID
Integer managerId = userDao.searchDeptManagerId(creatorId);
json.set("managerId", managerId); //部门经理ID
Integer gmId = userDao.searchGmId();//总经理ID
json.set("gmId", gmId);
//查询会议员工是不是同一个部门
boolean bool = meetingDao.searchMeetingMembersInSameDept(uuid);
json.set("sameDept", bool);
}
String url = workflow+"/workflow/startMeetingProcess";
//请求工作流接口,开启工作流
HttpResponse response = HttpRequest.post(url).header("Content-Type", "application/json").body(json.toString()).execute();
if (response.getStatus() == 200) {
json = JSONUtil.parseObj(response.body());
//如果工作流创建成功,就更新会议状态
String instanceId = json.getStr("instanceId");
HashMap param = new HashMap();
param.put("uuid", uuid);
param.put("instanceId", instanceId);
int row = meetingDao.updateMeetingInstanceId(param); //在会议记录中保存工作流实例的ID
if (row != 1) {
throw new EmosException("保存会议工作流实例ID失败");
}
}
}
} 综上所述,st_glFinish 函数在 Gallium3D 驱动层面上完成了等待命令完成和刷新前端缓冲区的操作。这是为了确保在继续执行代码之前,所有之前提交的OpenGL命令都已经执行完成,并将最终的渲染结果显示到屏幕上。