Anonymous
Отображение постоянно обновляющихся данных в opengl
Сообщение
Anonymous » 15 ноя 2024, 11:54
Я пытаюсь отобразить хронометр, а также постоянно обновляемые данные, такие как пройденное расстояние, в OpenGL. Также имеются кнопки для управления хронометром. Я планирую нарисовать текст на текстуре, а затем добавить текстуру в прямоугольную форму. (если есть лучший способ, сообщите мне)
У меня уже есть код для моего хронометра и других данных, но как мне передать эти данные в OpenGL?
(Использование Android Studio, OpenGL ES 2.0)
мой Java-код;
Код: Выделить всё
package com.example.code;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Chronometer;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.Locale;
public class Activity extends AppCompatActivity implements LocationListener {
private static final String TAG = "SpeedMeasurementActivity";
private LocationManager locationManager;
//private TextView currentSpeedTextView;
//private TextView distanceTextView;
private Chronometer chronometer;
private FloatingActionButton startStopButton;
private boolean isRunning = false;
private double totalDistance = 0;
private Location lastLocation;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_no_ar);
// Initialize views
//currentSpeedTextView = findViewById(R.id.speed_text_view);
//distanceTextView = findViewById(R.id.distance_text_view);
chronometer = findViewById(R.id.time_text_view);
startStopButton = findViewById(R.id.fab_startstop);
FloatingActionButton back = findViewById(R.id.fab_back);
// Initialize location manager
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
startStopButton.setOnClickListener(v -> {
if (!isRunning) {
startMeasurement();
} else {
stopMeasurement();
}
});
// Set up back button
back.setOnClickListener(v -> {
Intent intent1 = new Intent(getApplication(), ActivityMain.class);
startActivity(intent1);
finish();
});
}
private void startMeasurement() {
isRunning = true;
startStopButton.setImageResource(R.drawable.ic_action_stop);
startStopButton.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(code.this, R.color.red)));
chronometer.setBase(SystemClock.elapsedRealtime());
chronometer.start();
try {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
} catch (SecurityException e) {
Log.e(TAG, "request Location Updates error.", e);
}
}
private void stopMeasurement() {
isRunning = false;
startStopButton.setImageResource(R.drawable.ic_action_play);
startStopButton.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(code.this, R.color.green)));
chronometer.stop();
locationManager.removeUpdates(this);
}
@Override
public void onLocationChanged(@NonNull Location location) {
if (isRunning) {
double speed = location.getSpeed() * 3.6; // Convert m/s to km/h
currentSpeedTextView.setText(String.format(Locale.getDefault(), "%.1f km/h", speed));
if (lastLocation != null) {
float distance = lastLocation.distanceTo(location);
totalDistance += distance;
distanceTextView.setText(String.format(Locale.getDefault(), "%.2f m", totalDistance));
}
lastLocation = location;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
locationManager.removeUpdates(this);
}
// Implement other LocationListener methods (onStatusChanged, onProviderEnabled, onProviderDisabled)
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
@Override
public void onProviderEnabled(@NonNull String provider) {}
@Override
public void onProviderDisabled(@NonNull String provider) {}
}
MyGlSurfaceView.java;
Код: Выделить всё
package com.example.code;
import android.content.Context;
import android.opengl.GLSurfaceView;
public class MyGLSurfaceView extends GLSurfaceView {
private final Context mContext;
public GLRenderer renderer;
private static final String TAG = "MyGLSurfaceView";
public MyGLSurfaceView(Context context) {
super(context);
mContext=context;
setEGLContextClientVersion(2);
setEGLConfigChooser(8, 8, 8, 8, 16, 0);
renderer = new GLRenderer(context);
setRenderer(renderer);
}
}
TexRectangular.java;
Код: Выделить всё
package com.example.code;
import android.opengl.GLES20;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
public class TexRectangular {
private FloatBuffer vertexBuffer;
private ByteBuffer indexBuffer;
private FloatBuffer normalBuffer;
private FloatBuffer texcoordBuffer;
private float[] vertexs= new float[4*3];
private byte[] indexs= {
0,2,1,3
};
private float[] normals= {
0f,0f,1f,
0f,0f,1f,
0f,0f,1f,
0f,0f,1f
};
float textcoords[] = {
0f, 0f,
1f, 0f,
0f, 1f,
1f, 1f
};
TexRectangular() {
setRectangular(1f, 1f);
}
TexRectangular(float width, float height) {
setRectangular(width, height);
}
public void setRectangular(float width, float height) {
float top=height*.5f;
float bottom=-top;
float right=width*.5f;
float left=-right;
float[] vertexs= {
left, top, 0f,
right, top, 0f,
left, bottom, 0f,
right, bottom, 0f
};
vertexBuffer=BufferUtil.makeFloatBuffer(vertexs);
indexBuffer=BufferUtil.makeByteBuffer(indexs);
normalBuffer=BufferUtil.makeFloatBuffer(normals);
texcoordBuffer = BufferUtil.makeFloatBuffer(textcoords);
}
public void draw(float r,float g,float b,float a, float shininess) {
GLES20.glVertexAttribPointer(GLES.texcoordHandle, 2,
GLES20.GL_FLOAT, false, 0, texcoordBuffer);
GLES20.glVertexAttribPointer(GLES.positionHandle, 3,
GLES20.GL_FLOAT, false, 0, vertexBuffer);
GLES20.glVertexAttribPointer(GLES.normalHandle, 3,
GLES20.GL_FLOAT, false, 0, normalBuffer);
GLES20.glUniform4f(GLES.materialAmbientHandle, r, g, b, a);
GLES20.glUniform4f(GLES.materialDiffuseHandle, r, g, b, a);
GLES20.glUniform4f(GLES.materialSpecularHandle, 1f, 1f, 1f, a);
GLES20.glUniform1f(GLES.materialShininessHandle, shininess);
GLES20.glUniform4f(GLES.objectColorHandle, r, g, b, a);
//
indexBuffer.position(0);
GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP,
4, GLES20.GL_UNSIGNED_BYTE, indexBuffer);
}
}
StringTexture.java;
Код: Выделить всё
package com.example.code;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import javax.microedition.khronos.opengles.GL10;
public class StringTexture {
private int TextureId=-1;
private int TextureUnitNumber=0;
StringTexture(String text, float textSize, int txtcolor, int bkcolor, int textureidnumber) {
TextureUnitNumber = textureidnumber;
makeStringTexture(text, textSize, txtcolor, bkcolor);
}
StringTexture(String text, float textSize, int txtcolor, int bkcolor) {
makeStringTexture(text, textSize, txtcolor, bkcolor);
}
public void makeStringTexture(String text, float textSize, int txtcolor, int bkcolor) {
Paint paint = new Paint();
paint.setTextSize(textSize);
paint.setAntiAlias(true);
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
paint.getTextBounds(text, 0, text.length(), new Rect(0, 0, (int) textSize * text.length(), (int) textSize));
int textWidth = (int) paint.measureText(text);
int textHeight = (int) (Math.abs(fontMetrics.top) + fontMetrics.bottom);
if (textWidth == 0) textWidth = 10;
if (textHeight == 0) textHeight = 10;
int bitmapsize = 2;
while (bitmapsize < textWidth) bitmapsize *= 2;
while (bitmapsize < textHeight) bitmapsize *= 2;
Bitmap bitmap = Bitmap.createBitmap(bitmapsize, bitmapsize, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
paint.setColor(bkcolor);
canvas.drawRect(new Rect(0, 0, bitmapsize, bitmapsize), paint);
paint.setColor(txtcolor);
canvas.drawText(text, bitmapsize / 2 - textWidth / 2, bitmapsize / 2 - (fontMetrics.ascent + fontMetrics.descent) / 2, paint);
int FIRST_INDEX = 0;
final int DEFAULT_OFFSET = 0;
final int[] textures = new int[1];
if (TextureId!=-1) {
textures[FIRST_INDEX]=TextureId;
GLES20.glDeleteTextures(1, textures, DEFAULT_OFFSET);
}
GLES20.glGenTextures(1, textures, DEFAULT_OFFSET);
TextureId = textures[FIRST_INDEX];
// GLES20.glActiveTexture(GLES20.GL_TEXTURE0+TextureUnitNumber);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, TextureId);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
}
public void setTexture() {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0+TextureUnitNumber);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, TextureId);
GLES20.glUniform1i(GLES.textureHandle, TextureUnitNumber);
}
}
MyGLRenderer.java;
Код: Выделить всё
package com.example.code;
import android.content.Context;
import android.graphics.Color;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class MyGLRenderer implements GLSurfaceView.Renderer {
private final Context mContext;
private boolean validProgram=false;
private float aspect;
private float viewingangle = 45f;
private float[] LightPos={0f,0f,3f,0f};//x,y,z,1
private float[] pMatrix=new float[16];
private float[] mMatrix=new float[16];
private float[] cMatrix=new float[16];
private TexRectangular MyTexRectangular = new TexRectangular();
private StringTexture Speed;
private StringTexture Distance;
private StringTexture Time;
private static float[] DummyFloat= new float[1];
private static final FloatBuffer DummyBuffer=BufferUtil.makeFloatBuffer(DummyFloat);
MyGLRenderer(final Context context) {
mContext = context;
}
private String speedText = "";
private String distanceText = "";
private String timeText = "";
@Override
public void onSurfaceCreated(GL10 gl10,EGLConfig eglConfig) {
validProgram = GLES.makeProgram();
GLES20.glEnableVertexAttribArray(GLES.positionHandle);
GLES20.glEnableVertexAttribArray(GLES.normalHandle);
GLES20.glEnableVertexAttribArray(GLES.texcoordHandle);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glFrontFace(GLES20.GL_CCW);
GLES20.glCullFace(GLES20.GL_BACK);
GLES20.glUniform4f(GLES.lightAmbientHandle, 0.5f, 0.5f, 0.5f, 1.0f);
GLES20.glUniform4f(GLES.lightDiffuseHandle, 1f, 1f, 1f, 1.0f);
GLES20.glUniform4f(GLES.lightSpecularHandle, 0f, 0f, 0f, 0f);
GLES20.glClearColor(0f, 0f, 0f, 1.0f);
GLES20.glEnable(GLES20.GL_TEXTURE_2D);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
}
//set speed text
public void setSpeedText(float f){
//int speedInt;
String str;
//speed = f;
str = String.valueOf(f);
speedText = str + "km/h";
}
// set distance text
public void setDistanceText(float f){
//int distanceInt;
String str;
//distance = f;
str = String.valueOf(f);
distanceText = str + "m";
}
// set timer text
public void setTimeText(float f){
//int timeInt;
String str;
//time = f;
str = String.valueOf(f);
timeText = str;
}
@Override
public void onSurfaceChanged(GL10 gl10,int w,int h) {
GLES20.glViewport(0,0,w,h);
aspect=(float)w/(float)h;
}
@Override
public void onDrawFrame(GL10 glUnused) {
if (!validProgram) return;
GLES20.glVertexAttribPointer(GLES.positionHandle, 3, GLES20.GL_FLOAT, false, 0, DummyBuffer);
GLES20.glVertexAttribPointer(GLES.normalHandle, 3, GLES20.GL_FLOAT, false, 0, DummyBuffer);
GLES20.glVertexAttribPointer(GLES.texcoordHandle, 2, GLES20.GL_FLOAT, false, 0, DummyBuffer);
Speed = new StringTexture(speedText,16, Color.WHITE, Color.BLACK);
Distance = new StringTexture(distanceText,16, Color.WHITE, Color.BLACK);
Time = new StringTexture(timeText,16, Color.WHITE, Color.BLACK);
GLES.disableTexture();
GLES.enableShading();
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT |
GLES20.GL_DEPTH_BUFFER_BIT);
GLES.gluPerspective(pMatrix,
viewingangle,
aspect,
.01f,
120.0f);
GLES.setPMatrix(pMatrix);
float[] c1Matrix=new float[16];
float[] c2Matrix=new float[16];
Matrix.setLookAtM(c1Matrix, 0,
0f,0f,0f,
0.0f, 0.0f, -1.0f,
0.0f, 1.0f, 0.0f);
Matrix.multiplyMM(cMatrix, 0, c1Matrix, 0, c2Matrix, 0); //cMatrix = c1Matrix * c2Matrix
GLES.setCMatrix(cMatrix);
GLES.setLightPosition(LightPos);
GLES.disableShading();
GLES.enableShading();
GLES.enableTexture();
// Draw speed text
Matrix.setIdentityM(mMatrix, 0);
Matrix.translateM(mMatrix, 0, 0f, 1.0f, 0f); // Position for speed text
Matrix.scaleM(mMatrix, 0, 0.4f, 0.01f, 0.4f);
GLES.updateMatrix(mMatrix);
Speed.setTexture();
MyTexRectangular.draw(1f, 1f, 1f, 1f, 20.f);
// Draw distance text
Matrix.setIdentityM(mMatrix, 0);
Matrix.translateM(mMatrix, 0, 0f, 2.0f, 0f); // Position for distance text
Matrix.scaleM(mMatrix, 0, 0.4f, 0.01f, 0.4f);
GLES.updateMatrix(mMatrix);
Distance.setTexture();
MyTexRectangular.draw(1f, 1f, 1f, 1f, 20.f);
// Draw time text
Matrix.setIdentityM(mMatrix, 0);
Matrix.translateM(mMatrix, 0, 0f, 3.0f, 0f); // Position for time text
Matrix.scaleM(mMatrix, 0, 0.4f, 0.01f, 0.4f);
GLES.updateMatrix(mMatrix);
Time.setTexture();
MyTexRectangular.draw(1f, 1f, 1f, 1f, 20.f);
GLES.disableTexture();
}
}
p/s: если с моим кодом что-то не так, сообщите мне! я все еще борюсь, особенно с MyGLRenderer.java
Подробнее здесь:
https://stackoverflow.com/questions/791 ... -on-opengl
1731660852
Anonymous
Я пытаюсь отобразить хронометр, а также постоянно обновляемые данные, такие как пройденное расстояние, в OpenGL. Также имеются кнопки для управления хронометром. Я планирую нарисовать текст на текстуре, а затем добавить текстуру в прямоугольную форму. (если есть лучший способ, сообщите мне) У меня уже есть код для моего хронометра и других данных, но как мне передать эти данные в OpenGL? (Использование Android Studio, OpenGL ES 2.0) мой Java-код; [code]package com.example.code; import android.content.Context; import android.content.Intent; import android.content.res.ColorStateList; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.os.SystemClock; import android.util.Log; import android.widget.Chronometer; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; import com.google.android.material.floatingactionbutton.FloatingActionButton; import java.util.Locale; public class Activity extends AppCompatActivity implements LocationListener { private static final String TAG = "SpeedMeasurementActivity"; private LocationManager locationManager; //private TextView currentSpeedTextView; //private TextView distanceTextView; private Chronometer chronometer; private FloatingActionButton startStopButton; private boolean isRunning = false; private double totalDistance = 0; private Location lastLocation; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_no_ar); // Initialize views //currentSpeedTextView = findViewById(R.id.speed_text_view); //distanceTextView = findViewById(R.id.distance_text_view); chronometer = findViewById(R.id.time_text_view); startStopButton = findViewById(R.id.fab_startstop); FloatingActionButton back = findViewById(R.id.fab_back); // Initialize location manager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); startStopButton.setOnClickListener(v -> { if (!isRunning) { startMeasurement(); } else { stopMeasurement(); } }); // Set up back button back.setOnClickListener(v -> { Intent intent1 = new Intent(getApplication(), ActivityMain.class); startActivity(intent1); finish(); }); } private void startMeasurement() { isRunning = true; startStopButton.setImageResource(R.drawable.ic_action_stop); startStopButton.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(code.this, R.color.red))); chronometer.setBase(SystemClock.elapsedRealtime()); chronometer.start(); try { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this); } catch (SecurityException e) { Log.e(TAG, "request Location Updates error.", e); } } private void stopMeasurement() { isRunning = false; startStopButton.setImageResource(R.drawable.ic_action_play); startStopButton.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(code.this, R.color.green))); chronometer.stop(); locationManager.removeUpdates(this); } @Override public void onLocationChanged(@NonNull Location location) { if (isRunning) { double speed = location.getSpeed() * 3.6; // Convert m/s to km/h currentSpeedTextView.setText(String.format(Locale.getDefault(), "%.1f km/h", speed)); if (lastLocation != null) { float distance = lastLocation.distanceTo(location); totalDistance += distance; distanceTextView.setText(String.format(Locale.getDefault(), "%.2f m", totalDistance)); } lastLocation = location; } } @Override protected void onDestroy() { super.onDestroy(); locationManager.removeUpdates(this); } // Implement other LocationListener methods (onStatusChanged, onProviderEnabled, onProviderDisabled) @Override public void onStatusChanged(String provider, int status, Bundle extras) {} @Override public void onProviderEnabled(@NonNull String provider) {} @Override public void onProviderDisabled(@NonNull String provider) {} } [/code] MyGlSurfaceView.java; [code]package com.example.code; import android.content.Context; import android.opengl.GLSurfaceView; public class MyGLSurfaceView extends GLSurfaceView { private final Context mContext; public GLRenderer renderer; private static final String TAG = "MyGLSurfaceView"; public MyGLSurfaceView(Context context) { super(context); mContext=context; setEGLContextClientVersion(2); setEGLConfigChooser(8, 8, 8, 8, 16, 0); renderer = new GLRenderer(context); setRenderer(renderer); } } [/code] TexRectangular.java; [code]package com.example.code; import android.opengl.GLES20; import java.nio.ByteBuffer; import java.nio.FloatBuffer; public class TexRectangular { private FloatBuffer vertexBuffer; private ByteBuffer indexBuffer; private FloatBuffer normalBuffer; private FloatBuffer texcoordBuffer; private float[] vertexs= new float[4*3]; private byte[] indexs= { 0,2,1,3 }; private float[] normals= { 0f,0f,1f, 0f,0f,1f, 0f,0f,1f, 0f,0f,1f }; float textcoords[] = { 0f, 0f, 1f, 0f, 0f, 1f, 1f, 1f }; TexRectangular() { setRectangular(1f, 1f); } TexRectangular(float width, float height) { setRectangular(width, height); } public void setRectangular(float width, float height) { float top=height*.5f; float bottom=-top; float right=width*.5f; float left=-right; float[] vertexs= { left, top, 0f, right, top, 0f, left, bottom, 0f, right, bottom, 0f }; vertexBuffer=BufferUtil.makeFloatBuffer(vertexs); indexBuffer=BufferUtil.makeByteBuffer(indexs); normalBuffer=BufferUtil.makeFloatBuffer(normals); texcoordBuffer = BufferUtil.makeFloatBuffer(textcoords); } public void draw(float r,float g,float b,float a, float shininess) { GLES20.glVertexAttribPointer(GLES.texcoordHandle, 2, GLES20.GL_FLOAT, false, 0, texcoordBuffer); GLES20.glVertexAttribPointer(GLES.positionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer); GLES20.glVertexAttribPointer(GLES.normalHandle, 3, GLES20.GL_FLOAT, false, 0, normalBuffer); GLES20.glUniform4f(GLES.materialAmbientHandle, r, g, b, a); GLES20.glUniform4f(GLES.materialDiffuseHandle, r, g, b, a); GLES20.glUniform4f(GLES.materialSpecularHandle, 1f, 1f, 1f, a); GLES20.glUniform1f(GLES.materialShininessHandle, shininess); GLES20.glUniform4f(GLES.objectColorHandle, r, g, b, a); // indexBuffer.position(0); GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4, GLES20.GL_UNSIGNED_BYTE, indexBuffer); } } [/code] StringTexture.java; [code]package com.example.code; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.opengl.GLES20; import android.opengl.GLUtils; import javax.microedition.khronos.opengles.GL10; public class StringTexture { private int TextureId=-1; private int TextureUnitNumber=0; StringTexture(String text, float textSize, int txtcolor, int bkcolor, int textureidnumber) { TextureUnitNumber = textureidnumber; makeStringTexture(text, textSize, txtcolor, bkcolor); } StringTexture(String text, float textSize, int txtcolor, int bkcolor) { makeStringTexture(text, textSize, txtcolor, bkcolor); } public void makeStringTexture(String text, float textSize, int txtcolor, int bkcolor) { Paint paint = new Paint(); paint.setTextSize(textSize); paint.setAntiAlias(true); Paint.FontMetrics fontMetrics = paint.getFontMetrics(); paint.getTextBounds(text, 0, text.length(), new Rect(0, 0, (int) textSize * text.length(), (int) textSize)); int textWidth = (int) paint.measureText(text); int textHeight = (int) (Math.abs(fontMetrics.top) + fontMetrics.bottom); if (textWidth == 0) textWidth = 10; if (textHeight == 0) textHeight = 10; int bitmapsize = 2; while (bitmapsize < textWidth) bitmapsize *= 2; while (bitmapsize < textHeight) bitmapsize *= 2; Bitmap bitmap = Bitmap.createBitmap(bitmapsize, bitmapsize, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); paint.setColor(bkcolor); canvas.drawRect(new Rect(0, 0, bitmapsize, bitmapsize), paint); paint.setColor(txtcolor); canvas.drawText(text, bitmapsize / 2 - textWidth / 2, bitmapsize / 2 - (fontMetrics.ascent + fontMetrics.descent) / 2, paint); int FIRST_INDEX = 0; final int DEFAULT_OFFSET = 0; final int[] textures = new int[1]; if (TextureId!=-1) { textures[FIRST_INDEX]=TextureId; GLES20.glDeleteTextures(1, textures, DEFAULT_OFFSET); } GLES20.glGenTextures(1, textures, DEFAULT_OFFSET); TextureId = textures[FIRST_INDEX]; // GLES20.glActiveTexture(GLES20.GL_TEXTURE0+TextureUnitNumber); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, TextureId); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); bitmap.recycle(); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); } public void setTexture() { GLES20.glActiveTexture(GLES20.GL_TEXTURE0+TextureUnitNumber); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, TextureId); GLES20.glUniform1i(GLES.textureHandle, TextureUnitNumber); } } [/code] MyGLRenderer.java; [code]package com.example.code; import android.content.Context; import android.graphics.Color; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.opengl.Matrix; import java.nio.FloatBuffer; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; public class MyGLRenderer implements GLSurfaceView.Renderer { private final Context mContext; private boolean validProgram=false; private float aspect; private float viewingangle = 45f; private float[] LightPos={0f,0f,3f,0f};//x,y,z,1 private float[] pMatrix=new float[16]; private float[] mMatrix=new float[16]; private float[] cMatrix=new float[16]; private TexRectangular MyTexRectangular = new TexRectangular(); private StringTexture Speed; private StringTexture Distance; private StringTexture Time; private static float[] DummyFloat= new float[1]; private static final FloatBuffer DummyBuffer=BufferUtil.makeFloatBuffer(DummyFloat); MyGLRenderer(final Context context) { mContext = context; } private String speedText = ""; private String distanceText = ""; private String timeText = ""; @Override public void onSurfaceCreated(GL10 gl10,EGLConfig eglConfig) { validProgram = GLES.makeProgram(); GLES20.glEnableVertexAttribArray(GLES.positionHandle); GLES20.glEnableVertexAttribArray(GLES.normalHandle); GLES20.glEnableVertexAttribArray(GLES.texcoordHandle); GLES20.glEnable(GLES20.GL_DEPTH_TEST); GLES20.glEnable(GLES20.GL_CULL_FACE); GLES20.glFrontFace(GLES20.GL_CCW); GLES20.glCullFace(GLES20.GL_BACK); GLES20.glUniform4f(GLES.lightAmbientHandle, 0.5f, 0.5f, 0.5f, 1.0f); GLES20.glUniform4f(GLES.lightDiffuseHandle, 1f, 1f, 1f, 1.0f); GLES20.glUniform4f(GLES.lightSpecularHandle, 0f, 0f, 0f, 0f); GLES20.glClearColor(0f, 0f, 0f, 1.0f); GLES20.glEnable(GLES20.GL_TEXTURE_2D); GLES20.glEnable(GLES20.GL_BLEND); GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); } //set speed text public void setSpeedText(float f){ //int speedInt; String str; //speed = f; str = String.valueOf(f); speedText = str + "km/h"; } // set distance text public void setDistanceText(float f){ //int distanceInt; String str; //distance = f; str = String.valueOf(f); distanceText = str + "m"; } // set timer text public void setTimeText(float f){ //int timeInt; String str; //time = f; str = String.valueOf(f); timeText = str; } @Override public void onSurfaceChanged(GL10 gl10,int w,int h) { GLES20.glViewport(0,0,w,h); aspect=(float)w/(float)h; } @Override public void onDrawFrame(GL10 glUnused) { if (!validProgram) return; GLES20.glVertexAttribPointer(GLES.positionHandle, 3, GLES20.GL_FLOAT, false, 0, DummyBuffer); GLES20.glVertexAttribPointer(GLES.normalHandle, 3, GLES20.GL_FLOAT, false, 0, DummyBuffer); GLES20.glVertexAttribPointer(GLES.texcoordHandle, 2, GLES20.GL_FLOAT, false, 0, DummyBuffer); Speed = new StringTexture(speedText,16, Color.WHITE, Color.BLACK); Distance = new StringTexture(distanceText,16, Color.WHITE, Color.BLACK); Time = new StringTexture(timeText,16, Color.WHITE, Color.BLACK); GLES.disableTexture(); GLES.enableShading(); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); GLES.gluPerspective(pMatrix, viewingangle, aspect, .01f, 120.0f); GLES.setPMatrix(pMatrix); float[] c1Matrix=new float[16]; float[] c2Matrix=new float[16]; Matrix.setLookAtM(c1Matrix, 0, 0f,0f,0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f); Matrix.multiplyMM(cMatrix, 0, c1Matrix, 0, c2Matrix, 0); //cMatrix = c1Matrix * c2Matrix GLES.setCMatrix(cMatrix); GLES.setLightPosition(LightPos); GLES.disableShading(); GLES.enableShading(); GLES.enableTexture(); // Draw speed text Matrix.setIdentityM(mMatrix, 0); Matrix.translateM(mMatrix, 0, 0f, 1.0f, 0f); // Position for speed text Matrix.scaleM(mMatrix, 0, 0.4f, 0.01f, 0.4f); GLES.updateMatrix(mMatrix); Speed.setTexture(); MyTexRectangular.draw(1f, 1f, 1f, 1f, 20.f); // Draw distance text Matrix.setIdentityM(mMatrix, 0); Matrix.translateM(mMatrix, 0, 0f, 2.0f, 0f); // Position for distance text Matrix.scaleM(mMatrix, 0, 0.4f, 0.01f, 0.4f); GLES.updateMatrix(mMatrix); Distance.setTexture(); MyTexRectangular.draw(1f, 1f, 1f, 1f, 20.f); // Draw time text Matrix.setIdentityM(mMatrix, 0); Matrix.translateM(mMatrix, 0, 0f, 3.0f, 0f); // Position for time text Matrix.scaleM(mMatrix, 0, 0.4f, 0.01f, 0.4f); GLES.updateMatrix(mMatrix); Time.setTexture(); MyTexRectangular.draw(1f, 1f, 1f, 1f, 20.f); GLES.disableTexture(); } } [/code] p/s: если с моим кодом что-то не так, сообщите мне! я все еще борюсь, особенно с MyGLRenderer.java Подробнее здесь: [url]https://stackoverflow.com/questions/79191654/displaying-continuously-updating-data-on-opengl[/url]