wayland(xdg_wm_base) + egl + opengles 渲染使用纹理贴图的旋转 3D 立方体实例(十三)

news2024/11/25 0:58:01

文章目录

  • 前言
  • 一、使用 stb_image 库加载纹理图片
    • 1. 获取 stb_image.h 头文件
    • 2. 使用 stb_image.h 中的相关接口加载纹理图片
    • 3. 纹理图片——cordeBouee4.jpg
  • 二、渲染使用纹理贴图的旋转 3D 立方体
    • 1. egl_wayland_texture_cube.c
    • 2. Matrix.h 和 Matrix.c
    • 3. xdg-shell-client-protocol.h 和 xdg-shell-protocol.c
    • 4. 编译
    • 5. 运行
  • 三、不使用外部图片的纹理贴图的旋转3d 立方体
    • 1. egl_wayland_texture_cube3_0.c
    • 2. Matrix.h 和 Matrix.c
    • 3. xdg-shell-client-protocol.h 和 xdg-shell-protocol.c
    • 4. 编译
    • 5. 运行
  • 总结
  • 参考资料


前言

本文主要介绍如果使用 wayland(xdg_wm_base) + egl + opengles3.0 绘制一个使用纹理贴图的绕Y轴旋转的正方体,涉及纹理图片加载(stb_image.h)等相关知识
软硬件环境:
硬件:PC
软件:ubuntu22.04 egl1.4 opengles3.0 weston9.0


一、使用 stb_image 库加载纹理图片

stb_image 是一个非常轻量级的图像加载库,由 Sean Barrett 创建并维护。这个库以单个头文件的形式存在,可以直接包含到你的项目中,无需额外的编译和链接过程。
通过包含对应的头文件,可以使用 stb_image 来加载各种常见的图片格式,例如 JPEG、PNG 等

1. 获取 stb_image.h 头文件

可以在 stb_image 库github 仓库地址 找到该库的源代码和详细信息
对于本文只需要获取 stb_image.h 这个头文件即可,将stb_image.h 头文件放到自己的工程代码目录下,如下图所示
在这里插入图片描述

2. 使用 stb_image.h 中的相关接口加载纹理图片

在代码中添加 STB_IMAGE_IMPLEMENTATION 宏定义和 #include “stb_image.h”,然后使用 stbi_load() 函数接口加载 JPG图片,加载完成后就会得到图片的分辨率以及像素格式信息,在使用 glTexImage2D() 加载到纹理后,然后使用 stb_image_free() 释放相关的资源,如下代码所示

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

GLuint createTexture(void)
{
   
	GLuint textureId;
	int width, height, nrChannels;

	/* Generate a texture object. */
	glGenTextures(1, &textureId);

	unsigned char* data = stbi_load("./cordeBouee4.jpg", &width, &height, &nrChannels, 0);
	if (data) {
   
		printf("width = %d, height = %d, nrChannels = %d\n", width, height, nrChannels);
		GLenum format;
		if (nrChannels == 1)
			format = GL_RED;
		else if (nrChannels == 3)
			format = GL_RGB;
		else if (nrChannels == 4)
			format = GL_RGBA;

		/* Activate a texture. */
		glActiveTexture(GL_TEXTURE0);
		/* Bind the texture object. */
		glBindTexture(GL_TEXTURE_2D, textureId);
		/* Load the texture. */
		glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
		/* Set the filtering mode. */
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

		stbi_image_free(data);
	} else {
   
		printf("stbi_load picture failed\n");
	}

	return textureId;
}

3. 纹理图片——cordeBouee4.jpg

如下图片就是本文使用的纹理图片——cordeBouee4.jpg
cordeBouee4.jpg

二、渲染使用纹理贴图的旋转 3D 立方体

使用 opengles3.0 渲染一个使用纹理贴图的旋转3D立方体,代码如 egl_wayland_texture_cube.c 所示

1. egl_wayland_texture_cube.c

#include <wayland-client.h>
#include <wayland-server.h>
#include <wayland-egl.h>
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xdg-shell-client-protocol.h"
#include "Matrix.h"


#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#define WIDTH 800
#define HEIGHT 600

struct wl_display *display = NULL;
struct wl_compositor *compositor = NULL;
struct xdg_wm_base *wm_base = NULL;
struct wl_registry *registry = NULL;

//opengles global var

GLuint projectionLocation;
GLuint modelLocation;
GLuint viewLocation;
GLuint simpleCubeProgram;
GLuint samplerLocation;
GLuint textureId;


float projectionMatrix[16];
float modelMatrix[16];
float viewMatrix[16];
float angleX = 30.0f;
float angleY = 0.0f;
float angleZ = 0.0f;


struct window {
   
	struct wl_surface *surface;
    struct xdg_surface *xdg_surface;
	struct xdg_toplevel *xdg_toplevel;
	struct wl_egl_window *egl_window;
};

static void
xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
{
   
	xdg_wm_base_pong(shell, serial);
}

/*for xdg_wm_base listener*/
static const struct xdg_wm_base_listener wm_base_listener = {
   
	xdg_wm_base_ping,
};

/*for registry listener*/
static void registry_add_object(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) 
{
   
    if (!strcmp(interface, "wl_compositor")) {
   
        compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1);
    } else if (strcmp(interface, "xdg_wm_base") == 0) {
   
        wm_base = wl_registry_bind(registry, name,
            &xdg_wm_base_interface, 1);
        xdg_wm_base_add_listener(wm_base, &wm_base_listener, NULL);
    }
}


void registry_remove_object(void *data, struct wl_registry *registry, uint32_t name) 
{
   

}

static struct wl_registry_listener registry_listener = {
   registry_add_object, registry_remove_object};

static void
handle_surface_configure(void *data, struct xdg_surface *surface,
			 uint32_t serial)
{
   
	//struct window *window = data;

	xdg_surface_ack_configure(surface, serial);

	//window->wait_for_configure = false;
}

static const struct xdg_surface_listener xdg_surface_listener = {
   
	handle_surface_configure
};

static void
handle_toplevel_configure(void *data, struct xdg_toplevel *toplevel,
			  int32_t width, int32_t height,
			  struct wl_array *states)
{
   
}

static void
handle_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
{
   
}

static const struct xdg_toplevel_listener xdg_toplevel_listener = {
   
	handle_toplevel_configure,
	handle_toplevel_close,
};


bool initWaylandConnection()
{
   	
	if ((display = wl_display_connect(NULL)) == NULL)
	{
   
		printf("Failed to connect to Wayland display!\n");
		return false;
	}

	if ((registry = wl_display_get_registry(display)) == NULL)
	{
   
		printf("Faield to get Wayland registry!\n");
		return false;
	}

	wl_registry_add_listener(registry, &registry_listener, NULL);
	wl_display_dispatch(display);

	if (!compositor)
	{
   
		printf("Could not bind Wayland protocols!\n");
		return false;
	}

	return true;
}

bool initializeWindow(struct window *window)
{
   
	initWaylandConnection();
	window->surface = wl_compositor_create_surface (compositor);
	window->xdg_surface = xdg_wm_base_get_xdg_surface(wm_base, window->surface);
    if (window->xdg_surface == NULL)
    {
   
        printf("Failed to get Wayland xdg surface\n");
        return false;
    } else {
   
        xdg_surface_add_listener(window->xdg_surface, &xdg_surface_listener, window);
        window->xdg_toplevel =
            xdg_surface_get_toplevel(window->xdg_surface);
        xdg_toplevel_add_listener(window->xdg_toplevel,
            &xdg_toplevel_listener, window);
        xdg_toplevel_set_title(window->xdg_toplevel, "egl_wayland_texture");
    }

	return true;


}

void releaseWaylandConnection(struct window *window)
{
   
    if(window->xdg_toplevel)
        xdg_toplevel_destroy(window->xdg_toplevel);
    if(window->xdg_surface)
        xdg_surface_destroy(window->xdg_surface);
    wl_surface_destroy(window->surface);
    xdg_wm_base_destroy(wm_base);
    wl_compositor_destroy(compositor);
    wl_registry_destroy(registry);
    wl_display_disconnect(display);
}


bool createEGLSurface(EGLDisplay eglDisplay, EGLConfig eglConfig, EGLSurface *eglSurface, struct window *window)
{
   

	window->egl_window = wl_egl_window_create(window->surface, WIDTH, HEIGHT);
	if (window->egl_window == EGL_NO_SURFACE) {
    
		printf("Can't create egl window\n"); 
		return false;
	} else {
   
		printf("Created wl egl window\n");
	}

	*eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, window->egl_window, NULL);
	
	return true;
}


void deInitializeGLState(GLuint shaderProgram)
{
   
	// Frees the OpenGL handles for the program
	glDeleteProgram(shaderProgram);
}

void releaseEGLState(EGLDisplay eglDisplay)
{
   
	if (eglDisplay != NULL)
	{
   
		// To release the resources in the context, first the context has to be released from its binding with the current thread.
		eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);

		// Terminate the display, and any resources associated with it (including the EGLContext)
		eglTerminate(eglDisplay);
	}
}


//"    gl_Position = projection * modelView * vec4(vertexPosition, 1.0);\n"
static const char  glVertexShader[] 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1523172.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用 pnpm 搭建 monorepo 项目

引言 在我之前的开发经历中&#xff0c;并没有实际使用过 Monorepo 管理项目&#xff0c;尽管之前对此有所了解&#xff0c;但并未深入探究。然而&#xff0c;如今许多开源项目都采纳了 Monorepo 方式&#xff0c;对于不熟悉它的开发者来说&#xff0c;阅读和理解这些项目的源…

关于使用过别人的GitHub/Gitee账号提交东西到仓库后,自己的仓库提交失败问题的解决方法

目录 引言 问题出现的原因 问题的解决方法 打开控制面板 方法一&#xff1a; 方法二&#xff1a; 进入Windows凭据管理器 结语 引言 这个问题折磨了我将近三个小时&#xff0c;为了减少有人和我一样走弯路且防止自己忘记解决方法&#xff0c;便有了这篇文章。 问题出现…

【洛谷 P8602】[蓝桥杯 2013 省 A] 大臣的旅费 题解(图论+深度优先搜索+树的直径+链式前向星)

[蓝桥杯 2013 省 A] 大臣的旅费 题目描述 很久以前&#xff0c;T 王国空前繁荣。为了更好地管理国家&#xff0c;王国修建了大量的快速路&#xff0c;用于连接首都和王国内的各大城市。 为节省经费&#xff0c;T 国的大臣们经过思考&#xff0c;制定了一套优秀的修建方案&am…

uv 必备的工具 ps ai 全家桶合集

非常稀有的资源 &#xff0c;必应搜索 易品资源yipinziyuan 可以找到

浅谈如何自我实现一个消息队列服务器(1)——需求分析

文章目录 一、什么是消息队列&#xff1f;二、当下主流的消息队列(MQ)三、自我实现一个消息队列服务器的前期准备——需求分析3.1 核心概念3.2 broker server 核心概念3.2.1、虚拟主机&#xff08;Virtual Host&#xff09;3.2.2、交换机&#xff08;Exchange&#xff09;3.2.2…

如何构建Docker自定义镜像

说明&#xff1a;平常我们使用Docker运行各种容器&#xff0c;极大地方便了我们对开发应用的使用&#xff0c;如MySQL、Redis&#xff0c;以及各种中间件&#xff0c;使用时只要拉镜像&#xff0c;运行容器即可。本文介绍如何创建一个Demo&#xff0c;自定义构建一个镜像。 开…

基于 K8s 容器集群的容灾架构与方案

作者&#xff1a;庄宇 在设计系统架构时&#xff0c;我们必须假设任何组件和任何基础设施可能会在任何时间失效&#xff0c;例如&#xff1a;自然灾害&#xff0c;电力中断&#xff0c;网络中断&#xff0c;错误的系统变更等。为了应对挑战&#xff0c;我们必须设计合适的容灾…

HTML基础:head头部标签包含的8种形式详解

你好&#xff0c;我是云桃桃。 HTML <head> 标签用于定义文档的头部&#xff0c;包含了一些元数据和引用的外部资源&#xff0c;但并不会直接展示在页面上。<head> 标签位于 <html> 标签内部&#xff0c;紧跟在 <html> 开始标签之后&#xff0c;在 &l…

贪心算法(两个实例)

例一&#xff1a;调度问题 问题&#xff1a;由n项任务&#xff0c;每项任务的加工时间已知&#xff0c;从零时刻开始陆续加入一台机器上去加工&#xff0c;每个任务完成的时间是从0时刻到任务加工截至的时间。 求总完成时间&#xff08;所有任务完成时间最短计划方案&#xf…

C语言字符函数和字符串函数详解

Hello, 大家好&#xff0c;我是一代&#xff0c;今天给大家带来有关字符函数和字符串函数的有关知识 所属专栏&#xff1a;C语言 创作不易&#xff0c;望得到各位佬们的互三呦 一.字符函数 在C语言中有一些函数是专门为字符设计的&#xff0c;这些函数的使用都需要包含一个头文…

SQLiteC/C++接口详细介绍之sqlite3类(十七)

返回目录&#xff1a;SQLite—免费开源数据库系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十六&#xff09; 下一篇&#xff1a; SQLiteC/C接口详细介绍之sqlite3类&#xff08;十八&#xff09; ​ 53.sqlite3_trace_v2 函数功能&#x…

EXCEL+PYTHON学习3

1&#xff09; 遍历一个SHEET&#xff0c;无非就是两个循环&#xff0c;rows属性是取得所有行。 fn data3_16.xlsx wb openpyxl.load_workbook(fn) ws wb.active for row in ws.rows:for cell in row:print(cell.value, end )print() 2&#xff09; 返回工作表的最小行数…

【Leetcode-54.螺旋矩阵】

题目&#xff1a; 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5]示例 2&#xff1a; 输入&#xff1…

Day38:安全开发-JavaEE应用SpringBoot框架MyBatis注入Thymeleaf模版注入

目录 SpringBoot-Web应用-路由响应 SpringBoot-数据库应用-Mybatis SpringBoot-模版引擎-Thymeleaf 思维导图 Java知识点 功能&#xff1a;数据库操作&#xff0c;文件操作&#xff0c;序列化数据&#xff0c;身份验证&#xff0c;框架开发&#xff0c;第三方库使用等. 框架…

基于springboot实现房源出租信息系统项目【项目源码+论文说明】

基于springboot实现房源出租信息系统演示 摘要 近些年来在一线城市的房子需求量在逐步递增&#xff0c;其中租房子和出租房子的需求业务不断增加。那么租房对于我们一线二线城市来说是一个非常大&#xff0c;而且具有经济提升能力的业务场景。那么信息技术在此行业的加持早已是…

JavaWeb--HTML

一&#xff1a;HTML简介 *HTML是一门语言&#xff0c;所有的网页都是用HTML这门语言编写出来的&#xff1b; *HTML&#xff1a;超文本标记语言&#xff1b; 超文本&#xff1a;超越了文本的限制&#xff0c;比普通文本更强大。除了文字信息&#xff0c;还能定义图片&#xff…

展开说说:Android之SharedPreferences

SharedPreferences 是一种轻量级的数据持久化存储机制。以key/value键值对形式存储在xml文件&#xff0c;用于保存一些应用程序数据。保存在 /data/data/PACKAGE_NAME/shared_prefs/xxx.Xml文件。 SharedPreferences 只能存储string&#xff0c;int&#xff0c;float&#xff…

visual studio2019项目中引入头文件失效问题的解决

这几天把项目整理一下&#xff0c;但在引入头文件过程中非常曲折。 项目本身写好了可以运行&#xff0c;但是项目结构是这样的&#xff1a; 所以想把功能模块化&#xff0c;同一类协议功能放在一起。 于是建包&#xff0c;创建文件&#xff0c;导入头文件&#xff1a; 在新…

瑞熙贝通打造智慧校园实验室安全综合管理平台

一、建设思路 瑞熙贝通实验室安全综合管理平台是基于以实验室安全&#xff0c;用现代化管理思想与人工智能、大数据、互联网技术、物联网技术、云计算技术、人体感应技术、语音技术、生物识别技术、手机APP、自动化仪器分析技术有机结合&#xff0c;通过建立以实验室为中心的管…

zookeeper基础学习之六: zookeeper java客户端curator

简介 Curator是Netflix公司开源的一套zookeeper客户端框架&#xff0c;解决了很多Zookeeper客户端非常底层的细节开发工作&#xff0c;包括连接重连、反复注册Watcher和NodeExistsException异常等等。Patrixck Hunt&#xff08;Zookeeper&#xff09;以一句“Guava is to Java…