簡體   English   中英

以像素為單位查找OpenGL ES對象的高度

[英]Finding Height of OpenGL ES Object in Pixels

我的Android應用程序中有一個OpenGL ES 2.0 Surface,其中包含一個表示該視圖空間背景的對象。 我想找出如何確定整個對象的高度(包括屏幕下方的部分)的像素或dp。 對象本身是我創建的Sprite類的實例,該類在其構造函數中采用了視圖參數。

最終,我需要此高度數據,以便可以在平行布局中創建一個按鈕,該按鈕的高度與整個OpenGL Sprite對象(包括屏幕外部分)的高度完全相同。

我試過的

  • 使用精靈使用的紋理圖像的高度:由於某些顯而易見的原因,此方法不起作用。 圖片的高度為2048像素,但這不是它放置在openGL視圖內的精靈對象的高度,看起來單位也不同(世界空間與眼睛空間等)。
  • 使用矩形的高度實例化精靈:這不起作用,因為我不確定如何解決單位不匹配的問題。 我輸入到sprite構造函數中的rect對象具有以下參數:RectF(-3.0,-6.926641,3.0,41.07336),其中-6.9&41代表OpenGL視圖中sprite的頂部和底部。 如果我將按鈕設為〜48 dp或px高,則它當然不會與在設備屏幕上渲染的精靈的高度匹配。 再次是因為單位不匹配,按鈕使用了密度無關的像素,而精靈邊界使用了其他單位。

如何找到要尋找的身高值? 最好在dp中獲取此值,以便與按鈕的布局參數輕松進行1:1映射,但是我感覺我必須從px的OpenGL管道中獲取此值,然后手動轉換為dp。

下面的代碼(我遺漏了很多,因為我不想淹沒你們成千上萬的無關邏輯。如果我遺漏了任何可以幫助您理解的內容,請告訴我,我可以添加。)

OpenGL Renderer公共類OpenGL_GLRenderer實現GLSurfaceView.Renderer {

private int catNum = 0;
private OpenGL_FloatAnimator scroller;
private float offset = 0.0f;
private int frameHeight, frameWidth;    //height and width of the screen. Used for ortho view configuration
private float orthoTop, orthoBottom;

private final Context mActivityContext;
//texture objects

private OpenGL_TextureData catBoardTexture;
private OpenGL_SpriteClass catBoard; //sprite objects for background shape


/**
 * Store the model matrix. This matrix is used to move models from object space (where each model can be thought
 * of being located at the center of the universe) to world space.
 */
private float[] mModelMatrix = new float[16];

/**
 * Store the view matrix. This can be thought of as our camera. This matrix transforms world space to eye space;
 * it positions things relative to our eye.
 */
private float[] mViewMatrix = new float[16];

/** Store the projection matrix. This is used to project the scene onto a 2D viewport. */
private float[] mProjectionMatrix = new float[16];

/** Allocate storage for the final combined matrix. This will be passed into the shader program. */
private float[] mMVPMatrix = new float[16];

/** This will be used to pass in the transformation matrix. */
private int mMVPMatrixHandle;

/** This will be used to pass in the modelview matrix. */
private int mMVMatrixHandle;

/** This will be used to pass in model position information. */
private int mPositionHandle;

/** This will be used to pass in model color information. */
private int mColorHandle;

/** This will be used to pass in model normal information. */
private int mNormalHandle;

/** This will be used to pass in the texture. */
private int mTextureUniformHandle;

/** This will be used to pass in model texture coordinate information. */
private int mTextureCoordinateHandle;


/** This is a handle to our per-vertex cube shading program. */
private int catBoardProgramHandle;

/**
 * Initialize the model data.
 */
public OpenGL_GLRenderer(final Context context)
{
    mActivityContext = context;
    scroller = new OpenGL_FloatAnimator();//screen scroll animation object
}

protected string getVertexShader(int resourceID) {
    return OpenGL_RawResourceReader.readTextFileFromRawResource(mActivityContext, resourceID);
}

protected string getFragmentShader(int resourceID) {
    return OpenGL_RawResourceReader.readTextFileFromRawResource(mActivityContext, resourceID);
}

@Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);    // Set the background clear color to black.
    GLES20.glEnable(GLES20.GL_BLEND);              //Enable blending
    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);

    // Enable depth testing
    GLES20.glEnable(GLES20.GL_DEPTH_TEST);

    Matrix.setIdentityM(mViewMatrix, 0);

    //*************Shader Setup****************************
    //set handles to catboard shader programs
    final string vertexShader = getVertexShader(R.raw.vertex_shader);
    final string fragmentShader = getFragmentShader(R.raw.fragment_shader);

    //set handles to string shader programs
    final string stringVertexShader = getVertexShader(R.raw.string_vertex_shader);
    final string stringFragmentShader = getVertexShader(R.raw.string_fragment_shader);

    //compile catboard shader programs
    final int vertexShaderHandle = OpenGL_ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, vertexShader);
    final int fragmentShaderHandle = OpenGL_ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);

    //compile string shader programs
    final int stringVertexShaderHandle = OpenGL_ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, stringVertexShader);
    final int stringFragmentShaderHandle = OpenGL_ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, stringFragmentShader);

    //create and link compiled shader programs to catboard and string program handle variables
    catBoardProgramHandle = OpenGL_ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle,
            new string[]{"a_Position", "a_Color", "a_Normal", "a_TexCoordinate"});

    // Load images into Texture objects
    initializeTexture(cat);
    stringTexture = new OpenGL_TextureData(mActivityContext, R.drawable.texture_brass_string);
}

//sets up orthographic projection matrix
public void setupOrtho(int width, int height){
    // Create a new perspective projection matrix. The height will stay the same
    // while the width will vary as per aspect ratio.
    final float ratio = (float) width / height;
    final float near = -20.0f;
    final float far = 20.0f;
    final float screenWidth = 6.0f;
    final float left = -screenWidth/2.0f;
    final float right = -left;
    final float bottom = screenWidth/(2.0f*ratio);
    final float top = -bottom;
    orthoTop = top;
    orthoBottom = bottom;
    Matrix.orthoM(mProjectionMatrix, 0, left, right, bottom + scroller.getCurrentValue(), top+scroller.getCurrentValue(), near, far);
}

@Override
public void onSurfaceChanged(GL10 glUnused, int width, int height)
{
    frameHeight = height;
    frameWidth = width;
    GLES20.glViewport(0, 0, width, height);         //Set the OpenGL viewport to the same size as the surface.
    // Create a new perspective projection matrix. The height will stay the same
    // while the width will vary as per aspect ratio.
    setupOrtho(width, height);

    //Configure rectangles for sprites
    float heightBound = 6.0f*catBoardTexture.imageHeight/catBoardTexture.imageWidth; //6*h*w = (width of ortho projec. * aspect ratio)
    RectF catBoardBounds = new RectF(-3.0f, orthoTop, 3.0f, heightBound + orthoTop);

    //Configure Sprites!
    //scale,fit,repeat vertically, fill
    catBoard = new OpenGL_SpriteClass(catBoardTexture.textureID, catBoardTexture.imageWidth, catBoardTexture.imageHeight, catBoardBounds,0);
}

}

OpenGL SpriteClass

public class OpenGL_SpriteClass {
FloatBuffer positionBuffer;
FloatBuffer textureBuffer;
RectF _frame;
int _textureID;
//SizeF _textureSize;
Float textureWidth, textureHeight;

int mode; // TODO: use enumeration

boolean valid;

//public OpenGL_SpriteClass(int textureID, SizeF textureSize, RectF frame) {
public OpenGL_SpriteClass(int textureID, float txWidth, float txHeight, RectF frame, int modeNum) {
    setTextureID(textureID);
    setTextureSize(txWidth, txHeight);
    setFrame(frame);
    setMode(modeNum);
}

public void bindTexture() {
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _textureID);
}

public void setMode (int modeNum){
    valid = false;
    mode = modeNum;
    bindTexture();
    if (modeNum == 2){
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
    }
    else{
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
    }
}

public void setFrame(RectF frame) {
    // TODO: check if _frame is different from frame and invalidate
    valid = false;
    _frame = frame;
}

public void setTextureID(int textureID) {
    valid = false;
    _textureID = textureID;
}

/* public void setTextureSize(SizeF size) {
     // TODO: check if _textureSize is different from size and invalidate
     valid = false;
     _textureSize = size;
 }*/
public void setTextureSize(float textWidth, float textHeight) {
    // TODO: check if _textureSize is different from size and invalidate
    valid = false;
    textureWidth = textWidth;
    textureHeight = textHeight;
}

public FloatBuffer getPositionBuffer() {
    if(valid == false) {
        generateBuffers();
    }
    return positionBuffer;
}

public FloatBuffer getTextureBuffer() {
    if(valid == false) {
        generateBuffers();
    }
    return textureBuffer;
} ...}

OpenGL ES 2.0使用屏幕空間(– 1.0到+ 1.0)尺寸來定位精靈,但是使用像素空間尺寸來繪制它們。

將屏幕高度作為統一點傳遞到點頂點着色器,並使用該值計算gl_PointSize

onSurfaceChanged訪問以像素為單位的屏幕高度很簡單,但是如果要在OnSurfaceCreated中執行相同OnSurfaceCreated ,請使用以下int

context.getResources().getDisplayMetrics().heightPixels

感謝Reinier在此博客中發布了達到這一高度的方法

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM