gpt4 book ai didi

java - GLSurfaceView 交换正在绘制的 2D 位图

转载 作者:行者123 更新时间:2023-12-01 19:22:05 25 4
gpt4 key购买 nike

我有一个从数据库接收信息的应用程序,用于将 2D 位图可视化到 GLSurfaceView 上。收到的信息将确定位图的 x 位置以及要使用的位图图像(我的 res 文件夹中有 4 个不同的位图可供选择)。

下面是正在使用的三个类。 Activity 通过将 ArrayList 传递给 GLLayer 类来设置需要绘制的 Shapes 对象。此 ArrayList 通过另一个 setList 方法传递给 ShapeStorage 类的实例。这个类负责在收到它们时进行绘制。

我遇到的问题如下。假设我收到一个对象(假设它是一个位于 x=1 处的正方形)。一段时间过去了,我收到了另一个形状(这次是一个三角形,位于 x=-1 处)。但是,当这个新形状出现在屏幕上时,旧位图的外观将变为三角形,而新位图将变为正方形。换句话说,对象本身位于它们应该位于的正确位置,但与它们关联的位图已更改。有谁知道这可能是什么原因?我仍然是 OpenGL-ES 的新手,虽然这段代码看起来非常复杂,但它只涉及为 View 设置一堆不同的属性。请帮助我,StackOverflow!你是我唯一的希望。

public class GLLayer extends GLSurfaceView implements Renderer {
int onDrawFrameCounter=1;
int[] cameraTexture;
byte[] glCameraFrame=new byte[256*256]; //size of a texture must be a power of 2
private Context context;
FloatBuffer cubeBuff;
FloatBuffer texBuff;
ShapeStorage shapes;
ArrayList<Shapes> shapereceptionbuffer;

public GLLayer(Context c) {
super(c);
this.context=c;
//Initiate our stars class with the number of stars
shapes = new ShapeStorage();
shapereceptionbuffer=new ArrayList<Shapes>();

this.setEGLConfigChooser(5, 6, 5, 8, 16, 0);
this.setRenderer(this); //set the following class as a GLSurfaceView renderer
this.getHolder().setFormat(PixelFormat.TRANSPARENT); //makes the GLSurfaceView translucent

}

public void onSurfaceCreated(GL10 gl, EGLConfig config) {
try {
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glShadeModel(GL10.GL_SMOOTH); //Enable Smooth Shading
gl.glEnable(GL10.GL_TEXTURE_2D); //Enable Texture Mapping
gl.glEnable(GL10.GL_BLEND); //Enable blending
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //Black Background
gl.glClearDepthf(1.0f); //Depth Buffer Setup
gl.glDisable(GL10.GL_DEPTH_TEST); //Disable depth test
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); //Set The Blending Function For Translucency
shapes.setTextures(gl,context);



} catch (Exception e) {
// TODO Auto-generated catch block
Log.d("Created",e.getMessage());
}
}//end of surfacecreated

public void setList(ArrayList<Shapes> receivedList){
synchronized(this.shapereceptionbuffer){
shapereceptionbuffer=receivedList;

}
}

public void onSurfaceChanged(GL10 gl, int width, int height) {
try {

if(height == 0) { //Prevent A Divide By Zero By
height = 1; //Making Height Equal One
}

gl.glViewport(0, 0, width, height);//specifies transformation from normalized device coordinates to window coordinates
float ratio = (float) width / height;
gl.glMatrixMode(GL11.GL_PROJECTION); //Select The Projection Matrix
gl.glLoadIdentity();//Reset The Projection Matrix
GLU.gluPerspective(gl, 45.0f, ratio, 0.1f, 100.0f);
gl.glMatrixMode(GL11.GL_MODELVIEW);//Select The Modelview Matrix
gl.glLoadIdentity();//Reset The Modelview Matrix
} catch (Exception e) {
// TODO Auto-generated catch block
Log.d("Changed",e.getMessage());
}
//GLU.gluLookAt(gl, 0, 0, 4.2f, 0, 0, 0, 0, 1, 0);//eye-point location, center of the scene and an UP vector
}//end of surfacechanged

public void onDrawFrame(GL10 gl) {
try {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); //Clear Screen And Depth Buffer
Log.d("Buffer Size", String.valueOf(shapereceptionbuffer.size()));
synchronized(this.shapereceptionbuffer){

shapes.setShapes(shapereceptionbuffer);
shapes.draw(gl, this.context);
}

} catch (Exception e) {
Log.d("Draw",e.getMessage());
}
}//end of ondrawframe
}

此类负责绘制从外部数据库接收到的每个形状。

/**
* This class contains, loads, initiates textures and draws our Shapes
*/
public class ShapeStorage {
private ArrayList<Shapes> shapestoragebuffer;
private Random rand = new Random(); // Initiate Random for random values of
// stars

/** Our texture pointer */
private int[] textures = new int[4];

/**
* Constructor for our holder
*/
public ShapeStorage() {
shapestoragebuffer = new ArrayList<Shapes>();
}

public void setShapes(ArrayList<Shapes> receivedlist) {
shapestoragebuffer = receivedList;
}

public void setupTextures(GL10 gl, Context context) {
// Get the texture from the Android resource directory
InputStream is = null;
gl.glGenTextures(4, textures, 0);
for (int i = 2; i < 6; i++) {
switch (i) {
case 2:
is = context.getResources().openRawResource(R.drawable.square);
break;
case 3:
is = context.getResources().openRawResource(R.drawable.circle);
break;

case 4:
is = context.getResources().openRawResource(R.drawable.hexagon);
break;

case 5:
is = context.getResources()
.openRawResource(R.drawable.triangle);
break;
}

Bitmap bitmap = null;
try {
// BitmapFactory is an Android graphics utility for images
bitmap = BitmapFactory.decodeStream(is);

} finally {
// Always clear and close
try {
is.close();
is = null;
} catch (IOException e) {
}
}

// Generate the texture pointer

// Create Linear Filtered Texture and bind it to texture
GLUtils.texImage2D(GL11.GL_TEXTURE_2D, 0, bitmap, 0);
gl.glBindTexture(GL11.GL_TEXTURE_2D, textures[i - 2]);
gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER,
GL11.GL_LINEAR);
gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER,
GL11.GL_LINEAR);

// Clean up
bitmap.recycle();
}
}

/**
* The drawing function.
*
* @param gl
* - The GL Context
* @param twinkle
* - Twinkle on or off
*/
public void draw(GL10 gl, Context context) {
// Bind the icon texture for all Shapes



for (int loop = 0; loop < shapestoragebuffer.size(); loop++) {
// Recover the current star into an object
Shapes shape = shapestoragebuffer.get(loop);

gl.glLoadIdentity(); // Reset The Current Modelview Matrix
// gl.glRotatef(180.0f, -1.0f, 0.0f, 0.0f);
float x = shape.get_Offset_from_center();
gl.glTranslatef(x, 0.0f, -40.0f);

// Draw
switch (victim.getType()) {
// green
case 2:
shape.draw(gl, textures[0]);
break;
// red
case 3:
shape.draw(gl, textures[1]);
break;
// yellow
case 4:
shape.draw(gl, textures[2]);
break;

case 5:
shape.draw(gl, textures[3]);
break;
}

}
}
}

这里是定义每个被绘制到 GLSurfaceView 的对象的类;正在绘制的每个形状。

public class Shapes {


private int _Offset_from_center;
private int type;

Context c;
/** The buffer holding the vertices */
private FloatBuffer vertexBuffer;
/** The buffer holding the texture coordinates */
private FloatBuffer textureBuffer;

/** The initial vertex definition */
private float vertices[] = {
-1.0f, -1.0f, 0.0f, //Bottom Left
1.0f, -1.0f, 0.0f, //Bottom Right
-1.0f, 1.0f, 0.0f, //Top Left
1.0f, 1.0f, 0.0f //Top Right
};

/** The initial texture coordinates (u, v) */
private float texture[] = {
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
};
public Shapes() {
//
ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuf.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);

//
byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
}


public int get_Offset_from_center() {
return _Offset_from_center;
}

public void set_Offset_from_center(int _Offset_from_center) {
this._Offset_from_center = _Offset_from_center;
}

public int getType() {
return type;
}

public void setType(int type) {
this.type = type;
}

/**
* The object own drawing function.
* Called from the renderer to redraw this instance
* with possible changes in values.
*
* @param gl - The GL Context
*/
public void draw(GL10 gl,int texture) {
gl.glBindTexture(GL11.GL_TEXTURE_2D, texture);
//Enable the vertex, texture and normal state
gl.glEnableClientState(GL11.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

//Point to our buffers
gl.glVertexPointer(3, GL11.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, textureBuffer);

//Draw the vertices as triangle strip
gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, vertices.length / 3);

//Disable the client state before leaving
gl.glDisableClientState(GL11.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);


}


}

最佳答案

你对纹理做了一些非常奇怪的事情。为什么要在每一帧上上传每个形状的纹理图像数据,为什么要在渲染形状之后上传?

以下是 OpenGL 中纹理使用的常见流程:

在应用程序初始化时:

  1. 使用 glGenTextures 生成纹理 ID。
  2. 使用 glBindTexture 使该 ID 成为当前纹理。
  3. 设置纹理参数。
  4. 使用 texImage2D 或类似工具上传图像数据。

然后,每次您需要使用纹理渲染内容时:

  1. 使用与上面使用的相同 ID 的 glBindTexture 绑定(bind)纹理。
  2. 渲染将使用纹理的事物。

我在这里推荐的是:

当您的 Activity 启动时(从 onCreateonResume 间接调用,具体取决于 Android OpenGL 的工作方式):

  1. textures 设为 5 元素数组,并将 5 传递给 glGenTextures
  2. 循环遍历,对于五个资源中的每一个,绑定(bind)上述四个资源之一,然后使用 texImage2D 上传图像,就像您所做的那样。

然后,当您实际需要绘制形状时:

  1. 传入纹理的 int,而不是 int[];根据您想要的形状选择合适的。
  2. 首先使用该值在绘图函数中调用 glBindTexture
  3. 请勿在渲染 channel 中对 texImage2D 进行任何调用。
  4. 调用 glDrawArrays 绘制您使用 glBindTexture 选择的形状。

另请注意,所有形状都可以共享相同的顶点和纹理缓冲区,因为它们的内容相同;但这只是一个效率问题。

关于java - GLSurfaceView 交换正在绘制的 2D 位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3671564/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com