Flutter图形渲染插件glew的使用
Flutter图形渲染插件glew的使用
需求
- ffi ^2.1.2
注意事项
- Windows 64位系统
示例
在本示例中,我们将展示如何使用 glew
和 glfw3
在 Flutter 中实现一个简单的图形渲染。
作者
- yamahara
示例代码
// https://github.com/JoeyDeVries/LearnOpenGL/blob/master/src/1.getting_started/2.1.hello_triangle/hello_triangle.cpp
import 'dart:ffi';
import 'package:glew/glew.dart';
import 'package:glfw3/glfw3.dart';
// 设置屏幕宽度和高度
const gScrWidth = 800;
const gScrHeight = 600;
// 顶点着色器源码
final gVertexShaderSource = '#version 330 core'
'\n'
'layout (location = 0) in vec3 aPos;'
'\n'
'void main()'
'\n'
'{'
'\n'
' gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);'
'\n'
'}';
// 片段着色器源码
final gFragmentShaderSource = '#version 330 core'
'\n'
'out vec4 FragColor;'
'\n'
'void main()'
'\n'
'{'
'\n'
' FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);'
'\n'
'}';
int main() {
// 初始化并配置GLFW
// ------------------------------
if (glfwInit() != GLFW_TRUE) {
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// 对于苹果系统
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// 创建GLFW窗口
// --------------------
var window =
glfwCreateWindow(gScrWidth, gScrHeight, 'LearnOpenGL', nullptr, nullptr);
if (window == nullptr) {
print('Failed to create GLFW window');
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(
window, Pointer.fromFunction(framebufferSizeCallback));
// 加载所有OpenGL函数指针
// ---------------------------------------
gladLoadGLLoader(glfwGetProcAddress);
// 构建并编译着色器程序
// ------------------------------------
// 顶点着色器
var vertexShader = glCreateShader(GL_VERTEX_SHADER);
gldtShaderSource(vertexShader, gVertexShaderSource);
glCompileShader(vertexShader);
if (gldtGetShaderiv(vertexShader, GL_COMPILE_STATUS) != GLFW_TRUE) {
print('ERROR::SHADER::VERTEX::COMPILATION_FAILED');
var bufSize = gldtGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH);
if (bufSize > 1) {
print(gldtGetShaderInfoLog(vertexShader, bufSize));
}
}
// 片段着色器
var fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
gldtShaderSource(fragmentShader, gFragmentShaderSource);
glCompileShader(fragmentShader);
if (gldtGetShaderiv(fragmentShader, GL_COMPILE_STATUS) != GLFW_TRUE) {
print('ERROR::SHADER::FRAGMENT::COMPILATION_FAILED');
var bufSize = gldtGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH);
if (bufSize > 1) {
print(gldtGetShaderInfoLog(fragmentShader, bufSize));
}
}
// 链接着色器
var shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// 检查链接错误
if (gldtGetProgramiv(shaderProgram, GL_LINK_STATUS) != GL_TRUE) {
print('ERROR::SHADER::PROGRAM::LINKING_FAILED');
var bufSize = gldtGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH);
if (bufSize > 1) {
print(gldtGetProgramInfoLog(shaderProgram, bufSize));
}
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// 设置顶点数据
// ------------------------------------------------------------------
var vertices = [
-0.5, -0.5, 0.0, // 左下角
0.5, -0.5, 0.0, // 右下角
0.0, 0.5, 0.0, // 顶点
];
var vao = gldtGenVertexArrays(1)[0];
var vbo = gldtGenBuffers(1)[0];
// 绑定顶点数组对象,设置顶点缓冲区并配置顶点属性
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
gldtBufferFloat(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
gldtVertexAttribPointer(
0, 3, GL_FLOAT, GL_FALSE, 3 * sizeOf<Float>(), 0 * sizeOf<Float>());
glEnableVertexAttribArray(0);
// 解绑顶点缓冲区
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 渲染循环
// -----------
while (glfwWindowShouldClose(window) == GLFW_FALSE) {
// 处理输入
processInput(window);
// 渲染
glClearColor(0.2, 0.3, 0.3, 1);
glClear(GL_COLOR_BUFFER_BIT);
// 使用着色器程序
glUseProgram(shaderProgram);
// 绑定顶点数组对象
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
// 交换缓冲区并处理IO事件
glfwSwapBuffers(window);
glfwPollEvents();
}
// 清理资源
gldtDeleteVertexArrays([vao]);
gldtDeleteBuffers([vbo]);
glDeleteProgram(shaderProgram);
// 终止GLFW
glfwTerminate();
return 0;
}
// 处理所有输入
void processInput(Pointer<GLFWwindow> window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
}
// 当窗口大小改变时调用此回调函数
void framebufferSizeCallback(
Pointer<GLFWwindow> window, int width, int height) {
glViewport(0, 0, width, height);
}
更多关于Flutter图形渲染插件glew的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter图形渲染插件glew的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,直接使用GLEW(OpenGL Extension Wrangler Library)进行图形渲染并不是一个常见的做法,因为Flutter本身是基于Dart语言开发的,而GLEW是用于C/C++环境下OpenGL扩展加载的库。然而,如果你希望在Flutter应用中集成OpenGL渲染,你可以通过Flutter的Platform Channels与原生代码(如Android的Java/Kotlin或iOS的Swift/Objective-C)进行交互,并在原生代码中使用OpenGL和GLEW。
以下是一个简化的示例,展示了如何在Flutter中通过Platform Channels调用原生代码进行OpenGL渲染。由于GLEW的使用主要集中在OpenGL扩展的加载上,下面的示例将重点放在设置Platform Channels和OpenGL上下文上,而不是GLEW的具体使用(因为GLEW的使用与平台相关,且通常隐藏在OpenGL初始化和渲染代码中)。
1. 设置Flutter项目
首先,创建一个新的Flutter项目(如果你还没有的话):
flutter create flutter_glew_example
cd flutter_glew_example
2. 创建Platform Channel
在lib
目录下,修改main.dart
文件以设置Platform Channel:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
static const platform = MethodChannel('com.example.flutter_glew_example/channel');
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter GLEW Example'),
),
body: Center(
child: ElevatedButton(
onPressed: _setupOpenGL,
child: Text('Setup OpenGL'),
),
),
),
);
}
Future<void> _setupOpenGL() async {
try {
final result = await platform.invokeMethod('setupOpenGL');
print('OpenGL setup result: ${result}');
} on PlatformException catch (e) {
print("Failed to invoke: '${e.message}'.");
}
}
}
3. 实现原生代码
Android
在android/app/src/main/java/com/example/flutter_glew_example/
目录下,修改MainActivity.java
以处理Platform Channel调用:
package com.example.flutter_glew_example;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "com.example.flutter_glew_example/channel";
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler(
(call, result) -> {
if (call.method.equals("setupOpenGL")) {
setupOpenGL();
result.success("OpenGL setup complete");
} else {
result.notImplemented();
}
}
);
}
private void setupOpenGL() {
// Create and set a GLSurfaceView
GLSurfaceView glSurfaceView = new GLSurfaceView(this);
glSurfaceView.setEGLContextClientVersion(2); // OpenGL ES 2.0
glSurfaceView.setRenderer(new MyGLRenderer());
// Set the GLSurfaceView as the content view of the activity
setContentView(glSurfaceView);
}
// Define a simple OpenGL renderer
private static class MyGLRenderer implements GLSurfaceView.Renderer {
@Override
public void onSurfaceCreated(javax.microedition.khronos.opengles.GL10 gl, javax.microedition.khronos.egl.EGLConfig config) {
// Initialize OpenGL here (e.g., load shaders, set up buffers)
// GLEW would be used here if we were in a pure OpenGL/C++ environment
}
@Override
public void onSurfaceChanged(javax.microedition.khronos.opengles.GL10 gl, int width, int height) {
// Handle size changes here
}
@Override
public void onDrawFrame(javax.microedition.khronos.opengles.GL10 gl) {
// Render the frame here
}
}
}
iOS
在ios/Runner/
目录下,修改AppDelegate.swift
以处理Platform Channel调用(注意,iOS上设置OpenGL上下文通常涉及更复杂的UIKit和OpenGL ES集成):
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(name: "com.example.flutter_glew_example/channel", binaryMessenger: controller)
channel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
if call.method == "setupOpenGL" {
setupOpenGL()
result(Success("OpenGL setup complete"))
} else {
result(FlutterMethodNotImplemented)
}
})
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
func setupOpenGL() {
// Setting up OpenGL context on iOS is more complex and typically involves
// creating a CAEAGLLayer and integrating it with a UIView.
// GLEW usage would occur within the OpenGL rendering loop in Objective-C/Swift.
// Placeholder: You would initialize your OpenGL context and renderer here.
print("OpenGL setup placeholder on iOS")
}
}
4. 运行项目
现在,你可以运行Flutter项目,并在点击按钮时通过Platform Channel调用原生代码来设置OpenGL上下文。请注意,上面的代码示例并没有实际展示GLEW的使用,因为GLEW主要用于C/C++中的OpenGL扩展加载,而在Flutter的原生集成中,你通常会在OpenGL的初始化代码中直接处理所需的OpenGL函数和扩展。
如果你确实需要在Flutter项目中使用GLEW,你可能需要创建一个原生的C/C++模块,通过Dart FFI(外部函数接口)或直接通过Platform Channels与Flutter进行通信。然而,这通常不是Flutter开发的常规做法,因为Flutter提供了丰富的UI和渲染库,可以直接在Dart代码中使用。