gpt4 book ai didi

android - Opengl开发依赖GPU吗?

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:47:34 25 4
gpt4 key购买 nike

我正在用 opengl ES2.0 开发一个 android 应用程序。在这个应用程序中,我曾经在 GL surfaceView 中通过触摸事件绘制多条线和圆圈。

由于 opengl 依赖于 GPU,目前它在 Google Nexus 7(ULP GeForce) 中运行良好。

在 Samsung Galaxy Note 2(MALI 400MP) 中,我尝试绘制多条线,但它清除了前一行并将当前线绘制为新线。

在 Sony Xperia Neo V(Adreno 205) 中,我尝试绘制一条新线,它会破坏表面,如下图所示。 enter image description here

是否可以让它在所有设备上运行,还是我需要为单个 GPU 编写代码?


源代码

主 Activity .java

//in OnCreate method of my activity, i set the glsurfaceview and renderer

final ActivityManager activityManager =
( ActivityManager ) getSystemService( Context.ACTIVITY_SERVICE );
final ConfigurationInfo configurationInfo =
activityManager.getDeviceConfigurationInfo( );
final boolean supportsEs2 = ( configurationInfo.reqGlEsVersion >= 0x20000
|| Build.FINGERPRINT.startsWith( "generic" ) );

if( supportsEs2 ) {
Log.i( "JO", "configurationInfo.reqGlEsVersion:"
+ configurationInfo.reqGlEsVersion + "supportsEs2:"
+ supportsEs2 );
// Request an OpenGL ES 2.0 compatible context.
myGlsurfaceView.setEGLContextClientVersion( 2 );

final DisplayMetrics displayMetrics = new DisplayMetrics( );
getWindowManager( ).getDefaultDisplay( ).getMetrics( displayMetrics );

// Set the renderer to our demo renderer, defined below.
myRenderer = new MyRenderer( this, myGlsurfaceView );
myGlsurfaceView.setRenderer( myRenderer, displayMetrics.density );
myGlsurfaceView.setRenderMode( GLSurfaceView.RENDERMODE_CONTINUOUSLY );

MyGLSurfaceView.java
//in this im getting the coordinates of my touch on the glSurfaceView to draw the line and //passing those points to the renderer class
public MyGLsurfaceview( Context context ) {
super( context );
Log.i( "JO", "MyGLsurfaceview1" );

}

public MyGLsurfaceview(
Context context,
AttributeSet attrs )
{
super( context, attrs );
con = context;
mActivity = new MainActivity( );
mActivity.myGlsurfaceView = this;
Log.i( "JO", "MyGLsurfaceview2" );
}

public void setRenderer(
MyRenderer renderer,
float density )
{
Log.i( "JO", "setRenderer" );
myRenderer = renderer;
myDensity = density;
mGestureDetector = new GestureDetector( con, mGestureListener );
super.setRenderer( renderer );
setRenderMode( GLSurfaceView.RENDERMODE_CONTINUOUSLY );

}
@Override public boolean onTouchEvent( MotionEvent ev ) {

boolean retVal = mGestureDetector.onTouchEvent( ev );

if( myline ) {

switch ( ev.getAction( ) ) {

case MotionEvent.ACTION_DOWN:

isLUp = false;

if( count == 1 ) {
dx = ev.getX( );
dy = ev.getY( );
dx = ( dx / ( getWidth( ) / 2 ) ) - 1;
dy = 1 - ( dy / ( getHeight( ) / 2 ) );

firstX = dx;
firstY = dy;
} else if( count == 2 ) {

ux = ev.getX( );
uy = ev.getY( );
ux = ( ux / ( getWidth( ) / 2 ) ) - 1;
uy = 1 - ( uy / ( getHeight( ) / 2 ) );

secondX = ux;
secondY = uy;

myRenderer.dx = firstX;
myRenderer.dy = firstY;
myRenderer.ux = secondX;
myRenderer.uy = secondY;

midX = ( firstX + secondX ) / 2;
midY = ( firstY + secondY ) / 2;
Log.e( "JO",
"Line:firstX" + firstX +
"firstY" + firstY );
lp = new LinePoints( firstX, firstY,
secondX, secondY,
midX, midY );
lineArray.add( lp );

myRenderer.isNewClick = false;
myRenderer.isEnteredAngle = false;
myRenderer.myline = true;
myRenderer.mycircle = false;
myRenderer.mydashedline = false;
myRenderer.eraseCircle = false;
myRenderer.eraseLine = false;
myRenderer.eraseSelCir = false;
myRenderer.angle = angle;
myRenderer.length = length;
requestRender( );
count = 0;

}
count++;

break;
case MotionEvent.ACTION_MOVE:

isLUp = true;

break;

case MotionEvent.ACTION_UP:

if( isLUp ) {

ux = ev.getX( );
uy = ev.getY( );
ux = ( ux / ( getWidth( ) / 2 ) ) - 1;
uy = 1 - ( uy / ( getHeight( ) / 2 ) );
Log.i( "JO", "line2:" + ux + "," + uy );

secondX = ux;
secondY = uy;
myRenderer.dx = firstX;
myRenderer.dy = firstY;
myRenderer.ux = secondX;
myRenderer.uy = secondY;

midX = ( firstX + secondX ) / 2;
midY = ( firstY + secondY ) / 2;
Log.e( "JO",
"Line:firstX" + firstX +
"firstY" + firstY );
lp = new LinePoints( firstX, firstY,
secondX, secondY,
midX, midY );
lineArray.add( lp );

myRenderer.isNewClick = false;
myRenderer.isEnteredAngle = false;
myRenderer.myline = true;
myRenderer.mycircle = false;
myRenderer.mydashedline = false;
myRenderer.mysnaptoedge = false;
myRenderer.mysnaptoMiddle = false;
myRenderer.eraseCircle = false;
myRenderer.eraseLine = false;
myRenderer.eraseSelCir = false;
count = 1;
requestRender( );
}

break;

}
}
}
}

MyRenderer.java

//renderer class to render the line to the glsurfaceview
Lines line;
public MyRenderer(
MainActivity mainActivity,
MyGLsurfaceview myGlsurfaceView )
{
Log.i( "JO", "MyRenderer" );
this.main = mainActivity;
myGlsurface = myGlsurfaceView;

}

public void onDrawFrame(
GL10 gl )
{
line.draw( dx, dy, ux, uy );
}

@Override public void onSurfaceCreated(
GL10 gl,
EGLConfig config )
{
Log.i( "JO", "onSurfaceCreated" );
// Set the background frame color
GLES20.glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
// Create the GLText
glText = new GLText( main.getAssets( ) );

// Load the font from file (set size + padding), creates the texture
// NOTE: after a successful call to this the font is ready for
// rendering!
glText.load( "Roboto-Regular.ttf", 14, 2, 2 ); // Create Font (Height: 14
// Pixels / X+Y Padding
// 2 Pixels)
// enable texture + alpha blending
GLES20.glEnable( GLES20.GL_BLEND );
GLES20.glBlendFunc( GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA );
}

@Override public void onSurfaceChanged(
GL10 gl,
int width,
int height )
{
// Adjust the viewport based on geometry changes,
// such as screen rotation
GLES20.glViewport( 0, 0, width, height );

ratio = ( float ) width / height;

width_surface = width;
height_surface = height;

/*
* // this projection matrix is applied to object coordinates // in the
* onDrawFrame() method Matrix.frustumM(mProjMatrix, 0, -ratio, ratio,
* -1, 1, 3, 7);
*/
// Take into account device orientation
if( width > height ) {
Matrix.frustumM( mProjMatrix, 0, -ratio, ratio, -1, 1, 1, 10 );
} else {
Matrix.frustumM( mProjMatrix, 0, -1, 1, -1 / ratio, 1 / ratio,
1, 10 );
}

// Save width and height
this.width = width; // Save Current Width
this.height = height; // Save Current Height

int useForOrtho = Math.min( width, height );

// TODO: Is this wrong?
Matrix.orthoM( mVMatrix, 0, -useForOrtho / 2, useForOrtho / 2,
-useForOrtho / 2, useForOrtho / 2, 0.1f, 100f );
}

线.java

//Line class to draw line

public class Lines
{

final String vertexShaderCode = "attribute vec4 vPosition;"
+ "void main() {" + " gl_Position = vPosition;" + "}";

final String fragmentShaderCode = "precision mediump float;"
+ "uniform vec4 vColor;" + "void main() {"
+ " gl_FragColor = vColor;" + "}";

final FloatBuffer vertexBuffer;
final int mProgram;
int mPositionHandle;
int mColorHandle;

// number of coordinates per vertex in this array
final int COORDS_PER_VERTEX = 3;
float lineCoords[] = new float[6];
final int vertexCount = lineCoords.length / COORDS_PER_VERTEX;
final int vertexStride = COORDS_PER_VERTEX * 4; // bytes per vertex
// Set color with red, green, blue and alpha (opacity) values
float lcolor[] = { 1.0f, 1.0f, 1.0f, 1.0f };

public Lines(
)
{

// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
lineCoords.
length * 4 );
// use the device hardware's native byte order
bb.order( ByteOrder.nativeOrder( ) );

// create a floating point buffer from the ByteBuffer
vertexBuffer = bb.asFloatBuffer( );

// prepare shaders and OpenGL program
int vertexShader =
MyRenderer.loadShader( GLES20.GL_VERTEX_SHADER,
vertexShaderCode );
int fragmentShader =
MyRenderer.loadShader( GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode );

mProgram = GLES20.glCreateProgram( ); // create empty OpenGL Program
GLES20.glAttachShader( mProgram, vertexShader ); // add the vertex shader
// to program
GLES20.glAttachShader( mProgram, fragmentShader ); // add the fragment
// shader to program
GLES20.glLinkProgram( mProgram ); // create OpenGL program executables
}

public void draw(
float dX,
float dY,
float uX,
float uY )
{

lineCoords[0] = dX;
lineCoords[1] = dY;
lineCoords[2] = 0.0f;
lineCoords[3] = uX;
lineCoords[4] = uY;
lineCoords[5] = 0.0f;
Log.i( "JO",
"lineCoords:" + lineCoords[0] + "," + lineCoords[1] +
"," + lineCoords[3] + "," + lineCoords[4] );

vertexBuffer.put( lineCoords );
vertexBuffer.position( 0 );
// Add program to OpenGL environment
GLES20.glUseProgram( mProgram );

// get handle to vertex shader's vPosition member
mPositionHandle =
GLES20.glGetAttribLocation( mProgram, "vPosition" );

// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray( mPositionHandle );

// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer( mPositionHandle,
COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer );

// get handle to fragment shader's vColor member
mColorHandle =
GLES20.glGetUniformLocation( mProgram, "vColor" );

// Set color for drawing the triangle
GLES20.glUniform4fv( mColorHandle, 1, lcolor, 0 );
GLES20.glLineWidth( 3 );
// Draw the triangle
GLES20.glDrawArrays( GLES20.GL_LINES, 0, vertexCount );

// Disable vertex array
GLES20.glDisableVertexAttribArray( mPositionHandle );
}

}

最佳答案

好的,又来了:^1

OpenGL is not a scene graph. OpenGL does not maintain a scene, knows about objects or keeps tracks of geometry. OpenGL is a drawing API. You give it a canvas (in form of a Window or a PBuffer) and order it to draw points, lines or triangles and OpenGL does exactly that. Once a primitive (=point, line, triangle) has been drawn, OpenGL has no recollection about it whatsoever. If something changes, you have to redraw the whole thing.

重绘场景的正确步骤是:

  1. 禁用模板测试,以便后续步骤在整个窗口上运行。

  2. 使用 glClear(bits) 清除帧缓冲区,其中 bits 是一个位掩码,指定要清除 Canvas 的哪些部分。当渲染一个新帧时,你想清除所有东西,所以 bits = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;

  3. 设置视口(viewport),构建合适的投影矩阵

  4. 为场景中的每个对象加载正确的模型 View 矩阵、设置制服、选择顶点数组并进行绘图调用。

  5. 通过冲洗管线完成渲染。如果使用单缓冲窗口 glFinish(),如果使用双缓冲窗口调用 SwapBuffers。在更高级别的框架的情况下,这可能由框架执行。

重要 在双缓冲窗口上完成绘图后,您不得继续发送绘图操作,因为通过执行缓冲区交换,您正在绘制的后台缓冲区的内容是不明确的。因此,您必须重新开始绘图,从清除帧缓冲区开始(步骤 1 和 2)。

您的代码正是缺少这两个步骤。此外,我的印象是您正在执行 OpenGL 绘图调用以直接响应输入事件,可能在输入事件处理程序本身中。 不要这样做!。而是使用输入事件添加到图元列表(在您的情况下为线)进行绘制,然后发送重绘事件,这使框架调用绘图函数。在绘图函数中迭代该列表以绘制所需的线条。

重绘整个场景在 OpenGL 中是规范的!


[1](哎呀,我已经厌倦了每隔 3 个问题左右就得写这个……)

关于android - Opengl开发依赖GPU吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17229066/

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