三、opengles画三角形

news2024/12/24 3:36:13

第一部分Java端

1)界面

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <android.opengl.GLSurfaceView
        android:id="@+id/gl_surface"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

2)自定义MyGLSurfaceView

MyGLSurfaceView集成GLSurfaceView实现父类方法,并加载opengl相关参数和设置

自定义MyGLRender类实现GLSurfaceView.Renderer接口,并在其中引入jni相关的类方法

package com.example.onedrawtri2;

import android.content.Context;
import android.opengl.GLSurfaceView;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class MyGLSurfaceView extends GLSurfaceView {
    private MyRenderer renderer;

    public MyGLSurfaceView(Context context) {
        super(context);
        setEGLContextClientVersion(3);
        renderer = new MyRenderer();
        setRenderer(renderer);
        setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
    }
    private class MyRenderer implements GLSurfaceView.Renderer {
        @Override
        public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
            NativeImpl.NativeImpl_init();
        }

        @Override
        public void onSurfaceChanged(GL10 gl10, int width, int height) {
            NativeImpl.NativeImpl_OnSurfaceChanged(width, height);
        }

        @Override
        public void onDrawFrame(GL10 gl10) {
            NativeImpl.NativeImpl_draw();
        }
    }
}

3)jni方法

package com.example.onedrawtri2;

public class NativeImpl {
    static {
        System.loadLibrary("native-lib");
    }

    public static native void NativeImpl_init();
    public static native void NativeImpl_OnSurfaceChanged(int width,int height);
    public static native void NativeImpl_draw();
}

4)MainActivity引入加载MyGLSurfaceView

package com.example.onedrawtri2;

import androidx.appcompat.app.AppCompatActivity;

import android.opengl.GLSurfaceView;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    private GLSurfaceView gLView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        gLView = new MyGLSurfaceView(this);

        setContentView(gLView);
    }
}

第二部分C++端

1)native动态加载jni方法

//
// Created by CreatWall_zhouwen on 2023/4/11.
//

#include "jni.h"
#include <android/log.h>
#include <GLES2/gl2.h>
#include "Util.h"
#include "DrawTriangle.h"
#define NATIVE_RENDER_CLASS_NAME "com/example/onedrawtri2/NativeImpl"
#define TAG "GLTRIANGLE"
#ifdef __cplusplus
extern "C" {
#endif

/*
 * Class:     com_example_onedrawtri2_NativeImpl
 * Method:    init
 * Signature: ()V
 */
JNIEXPORT void JNICALL NativeImpl_init(JNIEnv *env, jobject instance)
{
    DrawTriangle::GetInstance();
    DrawTriangle::GetInstance()->CreateProgram();
}

/*
 * Class:     com_example_onedrawtri2_NativeImpl
 * Method:    OnSurfaceChanged
 * Signature: (II)V
 */
JNIEXPORT void JNICALL NativeImpl_OnSurfaceChanged(JNIEnv *env, jobject instance, jint width, jint height)
{
    glViewport(0, 0, width, height);
}

/*
 * Class:     com_example_onedrawtri2_NativeImpl
 * Method:    draw
 * Signature: ()V
 */
JNIEXPORT void JNICALL NativeImpl_draw(JNIEnv *env, jobject instance)
{
    DrawTriangle::GetInstance()->Draw();
}


#ifdef __cplusplus
}
#endif

static JNINativeMethod g_RenderMethods[] = {
		{"NativeImpl_init",             "()V",       (void *)(NativeImpl_init)},
		{"NativeImpl_OnSurfaceChanged",   "(II)V",     (void *)(NativeImpl_OnSurfaceChanged)},
		{"NativeImpl_draw",        "()V",       (void *)(NativeImpl_draw)},
};

static int RegisterNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods, int methodNum)
{
	LOGD("RegisterNativeMethods");
	jclass clazz = env->FindClass(className);
	if (clazz == NULL)
	{
		LOGD("RegisterNativeMethods fail. clazz == NULL");
		return JNI_FALSE;
	}
	if (env->RegisterNatives(clazz, methods, methodNum) < 0)
	{
		LOGD("RegisterNativeMethods fail");
		return JNI_FALSE;
	}
	return JNI_TRUE;
}

static void UnregisterNativeMethods(JNIEnv *env, const char *className)
{
	LOGD("UnregisterNativeMethods");
	jclass clazz = env->FindClass(className);
	if (clazz == NULL)
	{
		LOGD("UnregisterNativeMethods fail. clazz == NULL");
		return;
	}
	if (env != NULL)
	{
		env->UnregisterNatives(clazz);
	}
}

// call this func when loading lib
extern "C" jint JNI_OnLoad(JavaVM *jvm, void *p)
{
	LOGD("===== JNI_OnLoad =====");
	jint jniRet = JNI_ERR;
	JNIEnv *env = NULL;
	if (jvm->GetEnv((void **) (&env), JNI_VERSION_1_6) != JNI_OK)
	{
		return jniRet;
	}

	jint regRet = RegisterNativeMethods(env, NATIVE_RENDER_CLASS_NAME, g_RenderMethods,
										sizeof(g_RenderMethods) /
										sizeof(g_RenderMethods[0]));
	if (regRet != JNI_TRUE)
	{
		return JNI_ERR;
	}

	return JNI_VERSION_1_6;
}

extern "C" void JNI_OnUnload(JavaVM *jvm, void *p)
{
	JNIEnv *env = NULL;
	if (jvm->GetEnv((void **) (&env), JNI_VERSION_1_6) != JNI_OK)
	{
		return;
	}

	UnregisterNativeMethods(env, NATIVE_RENDER_CLASS_NAME);
}

2)opengles画三角形类

在里面实现了编写shader着色器,附加编译链接绑定着色器等相关操作。

DrawTriangle.h文件

//
// Created by CreatWall_zhouwen on 2023/4/3.
//

#ifndef ONEDRAWTRIANGLE_DRAWTRIANGLE_H
#define ONEDRAWTRIANGLE_DRAWTRIANGLE_H

#include <GLES3/gl3.h>
class DrawTriangle {
public:
    DrawTriangle(){};
    ~DrawTriangle(){};
    void CreateProgram();
    void Draw();
    static DrawTriangle* GetInstance();
    static void DestroyInstance();
private:
    GLuint program;
    GLuint vertexShaderHandle;
    GLuint fragShaderHandle;
    GLuint VBO, VAO;
};


#endif //ONEDRAWTRIANGLE_DRAWTRIANGLE_H

DrawTriangle.cpp文件

//
// Created by CreatWall_zhouwen on 2023/4/3.
//

#include "DrawTriangle.h"
#include <android/log.h>

#include "Util.h"
#define TAG "DRAWTRINGLE"
DrawTriangle* m_pContext = nullptr;
//编写顶点着色器代码
char vShaderStr[] =
        "#version 300 es                          \n"
        "layout(location = 0) in vec4 vPosition;  \n"
        "void main()                              \n"
        "{                                        \n"
        "   gl_Position = vPosition;\n"
        "}                                        \n";
//编写顶点着色器代码
char fShaderStr[] =
        "#version 300 es                              \n"
        "precision mediump float;                     \n"
        "out vec4 fragColor;                          \n"
        "void main()                                  \n"
        "{                                            \n"
        "   fragColor = vec4 ( 1.0f, 0.2f, 0.2f, 1.0f );  \n"
        "}                                            \n";
float vertices[] = {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f, 0.5f, 0.0f
};
void DrawTriangle::CreateProgram()
{
    LOGD("CreateProgram Enter");
    //程序中加载编译链接顶点着色器
    vertexShaderHandle = glCreateShader(GL_VERTEX_SHADER);//创建顶点着色器
    const char * s = vShaderStr;
    glShaderSource(vertexShaderHandle, 1, &s, NULL);//绑定源码
    glCompileShader(vertexShaderHandle);//编译
    GLint compiled = 0;
    glGetShaderiv(vertexShaderHandle, GL_COMPILE_STATUS, &compiled);//检查编译是否成功
    if (!compiled)
    {
        LOGD("CreateProgram vertexShaderHandle error");
        return;
    }

    //程序中加载编译链接片段着色器
    fragShaderHandle = glCreateShader(GL_FRAGMENT_SHADER);//创建顶片段着色器
    const char *s1 = fShaderStr;
    glShaderSource(fragShaderHandle, 1, &s1, NULL);//绑定源码
    glCompileShader(fragShaderHandle);//编译
    glGetShaderiv(fragShaderHandle, GL_COMPILE_STATUS, &compiled);//检查编译是否成功
    if (!compiled)
    {
        LOGD("CreateProgram fragShaderHandle error");
        return;
    }

    //创建程序
    program = glCreateProgram();
    if (program)
    {
        GLint AttachStatus = GL_FALSE;
        glAttachShader(program, vertexShaderHandle);//添加顶点着色器
        glGetProgramiv(program, GL_ATTACHED_SHADERS, &AttachStatus);//检查链接是否成功GL_ATTACHED_SHADERS
        if (AttachStatus != 1)
        {
            LOGD("AttachStatus vertexShaderHandle error");
            return;
        }
        GLint AttachStatus1 = GL_FALSE;
        glAttachShader(program, fragShaderHandle);//添加片段着色器
        glGetProgramiv(program, GL_ATTACHED_SHADERS, &AttachStatus1);//检查链接是否成功
        if (AttachStatus1 != 2)
        {
            LOGD("AttachStatus fragShaderHandle error glError (0x%x)  %d",glGetError(),AttachStatus1);
            return;
        }
        glLinkProgram(program);//链接
        GLint linkStatus = GL_FALSE;
        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);//检查链接是否成功
        if (linkStatus != GL_TRUE)
        {
            LOGD("CreateProgram glLinkProgram error");
            return;
        }
        //成功之后可以解绑着色器并删除调,使用完则删除内存
        glDetachShader(program, vertexShaderHandle);
        glDeleteShader(vertexShaderHandle);
        vertexShaderHandle = 0;
       glDetachShader(program, fragShaderHandle);
        glDeleteShader(fragShaderHandle);
        fragShaderHandle = 0;
    }

    glUseProgram(program);//使用着色器程序
    glGenVertexArrays(1, &VAO);//创建一个顶点数组 与顶点属性相绑定
    glGenBuffers(1, &VBO);//创建顶点缓冲对象
    glBindVertexArray(VAO);//绑定顶点数组

    glBindBuffer(GL_ARRAY_BUFFER, VBO);//将GL_ARRAY_BUFFER类型的缓存与VBO绑定
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//之前定义的顶点数据复制到缓冲的内存

    /*
        0;指定我们要配置的顶点属性 就是顶点着色器里面location那个
    */
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void *)0);
    glEnableVertexAttribArray(0);//以顶点属性位置值0作为参数,启用顶点属性

    //glBindBuffer(GL_ARRAY_BUFFER, 0);//VBO 已经与顶点属性数组VAO进行绑定了 那么GL_ARRAY_BUFFER就可以解除绑定
    //glBindVertexArray(0);//您可以在之后解除绑定VAO,这样其他VAO调用就不会意外地修改这个VAO*/
    LOGD("CreateProgram End");
    return;
}
void DrawTriangle::Draw()
{
    LOGD("Draw Enter");
    glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//使用状态函数
    glClearColor(0.2f, 0.9f, 0.3f, 1.0f); //设置状态函数



    glUseProgram(program);//使用着色器程序
    glBindVertexArray(VAO);//绑定顶点数组  就是使用顶点属性
    /*
    我们希望绘制的是一个三角形,这里传递GL_TRIANGLES给它。
    第二个参数指定了顶点数组的起始索引,我们这里填0。
    最后一个参数指定我们打算绘制多少个顶点,这里是3
    (我们只从我们的数据中渲染一个三角形,它只有3个顶点长)
    */
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glBindVertexArray(0);
    LOGD("Draw end");
}

DrawTriangle *DrawTriangle::GetInstance() {
    if (m_pContext == nullptr)
    {
        m_pContext = new DrawTriangle();
    }
    return m_pContext;
}

void DrawTriangle::DestroyInstance() {
    if (m_pContext)
    {
        delete m_pContext;
        m_pContext = nullptr;
    }
}

第三部分安卓配置文件配置

1)bulid.gradle(app)引入cmake

defaultConfig {
    ...
    externalNativeBuild {
        cmake {
            cppFlags ''
            abiFilters "arm64-v8a"
            //arguments "-DANDROID_STL=c++_shared"
        }
    }
}
externalNativeBuild {
    cmake {
        path file('src/main/cpp/CMakeLists.txt')
        version '3.10.2'
    }
}

2)settings.gradle文件配置链接

jcenter()

3)cmake文件

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.10.2)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

# Declares and names the project.
set(jnilibs ${CMAKE_SOURCE_DIR}/../jniLibs)
set(libname native-lib)

include_directories(
        include
        ${CMAKE_SOURCE_DIR}
)

link_directories(
        ${jnilibs}/${ANDROID_ABI})

file(GLOB src-files
        ${CMAKE_SOURCE_DIR}/*.cpp
        ${CMAKE_SOURCE_DIR}/drawTriangle.cpp
        )
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
        ${libname}

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        ${src-files}
        )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

#set(third-party-libs
#        GLES
#        )
set(native-libs
        android
        log
        m
        z
        )
target_link_libraries( # Specifies the target library.
        ${libname}

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib}
        ${native-libs}
        EGL
        GLESv3
        )

第四部分将着色器代码放到assets中引入

1)新建assets文件夹添加文件

在main文件夹上新建directory选择assets。

新建vertex.vs顶点着色器文件编写顶点着色器代码

#version 300 es
layout(location = 0) in vec4 vPosition;
void main()
{
    gl_Position = vPosition;
}

新建fragment.fs片段着色器文件编写片段着色器代码

#version 300 es
precision mediump float;
out vec4 fragColor;
void main()
{
    fragColor = vec4 ( 1.0f, 0.2f, 0.2f, 1.0f );
}

2)Java部分

private AssetManager mrg;
mrg = getResources().getAssets();
再调用native函数将mrg句柄传到native层次
NativeImpl.NativeImpl_InitScene(mrg);
JNI定义接口
public static native void NativeImpl_InitScene(Object mrg);

3)C++部分

创建一个读取assets资源的文件的接口

#ifndef C_NDKTEST_READFILEUTIL_H
#define C_NDKTEST_READFILEUTIL_H
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include "Util.h"
#define TAG "READFILEUTIL"
const char *LoadFileContent(const char *filepath);
AAssetManager *g_mrg;

const char *LoadFileContent(const char *filepath) {
    // read shader code form asset
    char *fileContent = nullptr;
    AAsset *asset = AAssetManager_open(g_mrg, filepath, AASSET_MODE_UNKNOWN);
    if (asset == nullptr) {
        // LOGE("LoadFileContent asset is null, load shader error ");
        LOGD("LoadFileContent asset is null, load shader error ");
    }
    int filesSize_v = AAsset_getLength(asset);
    fileContent = new char[filesSize_v];
    AAsset_read(asset, fileContent, filesSize_v);
    fileContent[filesSize_v] = '\0';
    AAsset_close(asset);
    LOGD("LoadFileContent asset is %s", fileContent);
    return fileContent;
}

#endif //C_NDKTEST_READFILEUTIL_H

在jni中使用

JNI函数native接口是实现
/*
 * Class:     com_example_onedrawtri2_NativeImpl
 * Method:    NativeImpl_InitScene
 * Signature: (Ljava/lang/Object;)V
 */
JNIEXPORT void JNICALL NativeImpl_InitScene(JNIEnv *env, jobject instance, jobject msg)
{
   g_mrg = AAssetManager_fromJava(env, msg);
}

//使用读取内容
/*
 * Class:     com_example_onedrawtri2_NativeImpl
 * Method:    init
 * Signature: ()V
 */
JNIEXPORT void JNICALL NativeImpl_init(JNIEnv *env, jobject instance)
{
    DrawTriangle::GetInstance();
    DrawTriangle::GetInstance()->CreateProgram(LoadFileContent("vertex.vs"), LoadFileContent("fragment.fs"));
}

第五部分多种颜色的三角形

添加 vColor属性

1)顶点着色器

#version 300 es
layout(location = 0) in vec4 vPosition;
layout(location = 1) in vec3 vColor;
out vec3 ourColor;
void main()
{
    gl_Position = vPosition;
    ourColor = vColor;
}

片段着色器

#version 300 es
precision mediump float;
out vec4 fragColor;
in vec3 ourColor;
void main()
{
    fragColor = vec4 ( ourColor.rgb, 1.0 );
}

顶点坐标添加颜色属性

float verticesCor[] = {
        // positions         // colors
        0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,   // bottom right
        -0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,   // bottom left
        0.0f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f    // top
};

2)添加颜色属性绑定顶点坐标

/*
    0;指定我们要配置的顶点属性 就是顶点着色器里面location那个
*/
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (void *)0);
glEnableVertexAttribArray(0);//以顶点属性位置值0作为参数,启用顶点属性

/*
 * 1、配置颜色属性
 */
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (void *)(3*sizeof(float)));
glEnableVertexAttribArray(1);//以顶点属性位置值0作为参数,启用顶点属性

参考链接:

https://blog.csdn.net/one_chow_chow/article/details/125888904 NDK OpenGL ES 3.0 :画个三角形

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

数据中台浅析——概念、架构以及未来

数据中台浅析 1. 引言 在当今的数字化时代&#xff0c;数据被誉为"新的石油"&#xff0c;越来越多的企业和组织开始深度挖掘数据的价值。在这个过程中&#xff0c;数据中台逐渐成为了数据管理和分析的核心架构&#xff0c;让我们来深入了解一下它。 1.1 数据中台…

算法复杂度分析(一)

求第n个斐波那契数列 斐波那契数 0 1 1 2 3 5 数列默认从0开始 public static int fib1(int n) {if(n < 1) return n;return fib1(n-1) fib1(n-2);}public static int fib2(int n) {if(n < 1) return n;int first 0;int secend 1;for (int i 0; i < n-1; i) {int…

七、帧缓冲离屏渲染

第一部分基础概念 1)两种帧缓冲的由来 首先opengl能够显示到屏幕&#xff0c;也是有一个默认的framebuffer由窗口系统创建并管理的&#xff0c;将数据放到默认framebuffer 中就可以显示到屏幕上。但是应用程序也想创建额外的非可显示的framebuffer。 应用程序自己创建FBO也是…

【2023RT-Thread全球技术峰会】一套全新的物联网多应用框架xiotman,助你解决多应用的难题

写在前面 就在上周&#xff0c;我作为讲师参与了2023RT-Thread全球技术峰会的主题演讲&#xff0c;我给大家带来了一套全新的解决物联网终端应用多样化的软件架构解决方案&#xff0c;在这里我再次以图文的形式介绍一下给社区的小伙伴&#xff0c;希望借此机会找到更多的同频小…

Nginx优化、Nginx+Tomcat实现负载均衡、动静分离集群部署

Nginx优化、NginxTomcat实现负载均衡、动静分离集群部署 一、Tomcat 优化二、Tomcat多实例部署1、安装好jdk2、安装tomcat3、配置tomcat环境变量4、修改tomcat2中的server.xml文件&#xff0c;要求各tomcat实例配置不能有重复的端口号5、修改各tomcat实例中的startup.sh和shutd…

ARM--$2$驱动模块

目录 1.驱动模块&#xff08;驱动程序的框架&#xff09; 2.内核中的打印函数&#xff08;编写第一个驱动程序&#xff09; Source Insight 使用&#xff1a; 打印函数编写 分析 3.驱动的多文件编译 4.模块传递参数 安装好驱动之后如何传参&#xff1f; 多驱动之间调用…

js内存管理与闭包

JavaScript内存管理 ◼ 不管什么样的编程语言&#xff0c;在代码的执行过程中都是需要给它分配内存的&#xff0c;不同的是某些编程语言需要我们自己手动的管理内存&#xff0c; 某些编程语言会可以自动帮助我们管理内存&#xff1a; ◼ 不管以什么样的方式来管理内存&#xf…

扩展系统功能——装饰模式(二)

装饰模式概述 装饰模式可以在不改变一个对象本身功能的基础上给对象增加额外的新行为&#xff0c;在现实生活中&#xff0c;这种情况也到处存在&#xff0c;例如一张照片&#xff0c;我们可以不改变照片本身&#xff0c;给它增加一个相框&#xff0c;使得它具有防潮的功能&…

安装Unity Hub和Unity Editor

1、首先下载UnityHub的安装包&#xff1a; https://unity.com/cn/download 开始您的创意项目并下载 Unity Hub | Unity 2、运行安装包 3、运行Unity Hub 第一次运行Unity Hub会默认弹出登录Unity提示&#xff0c;正常登录就可以了&#xff0c;登录后会在浏览器提示打开 Unity…

nginx+lua(openresty) 安装及使用(一)

前言 OpenResty —— 通过 Lua 扩展 NGINX 实现的可伸缩的 Web 平台。 OpenResty&#xff08;也称为 ngx_openresty&#xff09;是一个基于 Nginx 与 Lua 的高性能 Web 平台&#xff0c;其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超…

全志V3S嵌入式驱动开发(lcd屏幕驱动)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 对于一些设备&#xff0c;人们是希望从屏幕上面获取结果信息的&#xff0c;这样也显得更直观一些。另外&#xff0c;也有一些设备&#xff0c;它本…

阿里云OSS实现图片上传(后端接口)

文章目录 1、阿里云oss服务开通2、java操作阿里云oss&#xff0c;上传文件到阿里云oss1. 创建操作阿里云oss许可证2. 安装SDK3.修改配置文件4.创建常量类&#xff0c;读取配置文件中的内容5、OssController6、OssService7、OssServiceImpl8、改进1. 多次上传相同名称文件&#…

Segment Anything学习小结

论文地址&#xff1a;Segment Anything 项目地址&#xff1a;https://github.com/facebookresearch/segment-anything 在线Demo&#xff1a; https://segment-anything.com/demo 前言 近日&#xff0c;MetaAI团队开源了一个用于分割的10亿个masks&#xff0c;1100w张图片数…

测试新手如何晋升为月入过万的软件测试工程师?“我“的测试之路不简单...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 测试工程师这个岗…

记一次binlog恢复Mysql某张表数据的过程

1、备份数据库&#xff0c;非常重要 2、要用户不能操作&#xff08;如果不能停止&#xff0c;可以新建一个库&#xff0c;所有的binlog执行操作在新库执行&#xff09;。 3、登录服务器&#xff1b; 4、获取Mysql数据路径 cat /etc/my.cnf.d/mysql-server.cnf5、进入当前目录…

【SpinalHDL快速入门】4.2、基本类型之Bits

文章目录 1.1、描述1.2、声明1.3、运算符1.3.1、逻辑运算&#xff08;Logic&#xff09;1.3.2、比较&#xff08;Comparison&#xff09;1.3.3、类型转换&#xff08;Type cast&#xff09;1.3.4、部分赋值/提取操作符&#xff08;Bit extraction&#xff09;1.3.5、杂项&#…

Redis的使用规范小建议

Redis 核心技术与实战 笔记 作者&#xff1a; 蒋德钧 毕竟&#xff0c;高性能和节省内存&#xff0c;是我们的两个目标&#xff0c;只有规范地使用Redis&#xff0c;才能真正实现这两个目标。如果说之前的内容教会了你怎么用&#xff0c;那么今天的内容&#xff0c;就是帮助你用…

ChatGPT的学习过程【分析ChatGPT原理】+如何高效使用GPT

ChatGPT的学习过程【分析ChatGPT原理】如何高效使用GPT 此处借鉴&#xff1a;台湾大学李宏毅老师的讲解 资料&#xff1a;pan.baidu.com/s/1Jk1phne3ArfOERYNTPL12Q?pwd1111 GPTGenerative Pre-trained Transformer生成式预训练转换模型 ChatGPT共有四个学习阶段 学习文字接龙…

Java性能权威指南-总结7

Java性能权威指南-总结7 垃圾收集算法理解Throughput收集器堆大小的自适应调整和静态调整理解CMS收集器 垃圾收集算法 理解Throughput收集器 Throughput收集器有两个基本的操作&#xff1b;其一是回收新生代的垃圾&#xff0c;其二是回收老年代的垃圾。 下图展示了堆在新生代…

Python配置MySQL数据库使用

创建配置文件 config.ini [MySQL] host 172.xxx.xxx.xxx port 3306 user root password ****** db bgp_routing charset utf8创建读取配置文件 readConfig.py import configparser from pathlib import Pathclass ReadConfig():def __init__(self):configDir Path.cwd…