gpt4 book ai didi

Android OpenGL ES 2 纹理象限旋转

转载 作者:行者123 更新时间:2023-11-29 00:27:32 24 4
gpt4 key购买 nike

我正在尝试将一个简单的 2D 纹理加载到一个正方形上,并将其显示在我的 GLSurfaceView 的背面。我已经复制并修复了 Draw a 2D Image using OpenGL ES 2.0 中的代码,但是当我安装并运行应用程序时,图像被分成 4 个象限,然后重新排列。

这是我实现的 Sprite 类:

public class Sprite {
//Reference to Activity Context
private final Context mActivityContext;

//Added for Textures
private final FloatBuffer mCubeTextureCoordinates;
private int mTextureUniformHandle;
private int mTextureCoordinateHandle;
private final int mTextureCoordinateDataSize = 2;
private int mTextureDataHandle;

private final String vertexShaderCode =
//Test
"attribute vec2 a_TexCoordinate;" +
"varying vec2 v_TexCoordinate;" +
//End Test
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
//Test
"v_TexCoordinate = a_TexCoordinate;" +
//End Test
"}";

private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 v_Color;" +
//Test
"uniform sampler2D u_Texture;" +
"varying vec2 v_TexCoordinate;" +
//End Test
"void main() {" +
//"gl_FragColor = v_Color;" +
//"gl_FragColor = (v_Color * texture2D(u_Texture, v_TexCoordinate));" +
// Just draw the texture, don't apply a color
"gl_FragColor = texture2D(u_Texture, v_TexCoordinate);" +
"}";

private final int shaderProgram;
private final FloatBuffer vertexBuffer;
private final ShortBuffer drawListBuffer;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;

// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 2;

static float spriteCoords[] = {
-0.5f, 0.5f, // top left
-0.5f, -0.5f, // bottom left
0.5f, -0.5f, // bottom right
0.5f, 0.5f //top right
};

private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; //Order to draw vertices
private final int vertexStride = COORDS_PER_VERTEX * 4; //Bytes per vertex

// Set color with red, green, blue and alpha (opacity) values
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };

// Image to draw as a texture
final int textureID = R.raw.quadrants;

public Sprite(final Context activityContext) {
mActivityContext = activityContext;

//Initialize Vertex Byte Buffer for Shape Coordinates / # of coordinate values * 4 bytes per float
ByteBuffer bb = ByteBuffer.allocateDirect(spriteCoords.length * 4);
//Use the Device's Native Byte Order
bb.order(ByteOrder.nativeOrder());
//Create a floating point buffer from the ByteBuffer
vertexBuffer = bb.asFloatBuffer();
//Add the coordinates to the FloatBuffer
vertexBuffer.put(spriteCoords);
//Set the Buffer to Read the first coordinate
vertexBuffer.position(0);

// S, T (or X, Y)
// Texture coordinate data.
// Because images have a Y axis pointing downward (values increase as you move down the image) while
// OpenGL has a Y axis pointing upward, we adjust for that here by flipping the Y axis.
// What's more is that the texture coordinates are the same for every face.
final float[] cubeTextureCoordinateData =
{
//Front face
/*0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f*/
/*
This was in the code in the aforementioned StackOverflow post,
but doesn't work either
-0.5f, 0.5f,
-0.5f, -0.5f,
0.5f, -0.5f,
0.5f, 0.5f
*/
0.5f, 0.5f,
0.5f, -0.5f,
-0.5f, -0.5f,
-0.5f, 0.5f

};

mCubeTextureCoordinates = ByteBuffer
.allocateDirect(cubeTextureCoordinateData.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mCubeTextureCoordinates.put(cubeTextureCoordinateData).position(0);

//Initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(spriteCoords.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);

int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);

shaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(shaderProgram, vertexShader);
GLES20.glAttachShader(shaderProgram, fragmentShader);

//Texture Code
GLES20.glBindAttribLocation(shaderProgram, 0, "a_TexCoordinate");

GLES20.glLinkProgram(shaderProgram);

//Load the texture
mTextureDataHandle = loadTexture(mActivityContext, textureID);
}

public void draw(float[] mvpMatrix) {
//Add program to OpenGL ES Environment
GLES20.glUseProgram(shaderProgram);

//Get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(shaderProgram, "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 v_Color member
mColorHandle = GLES20.glGetUniformLocation(shaderProgram, "v_Color");

//Set the Color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);

//Set Texture Handles and bind Texture
mTextureUniformHandle = GLES20.glGetAttribLocation(shaderProgram, "u_Texture");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(shaderProgram, "a_TexCoordinate");

//Set the active texture unit to texture unit 0.
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);

//Bind the texture to this unit.
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle);

//Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
GLES20.glUniform1i(mTextureUniformHandle, 0);

//Pass in the texture coordinate information
mCubeTextureCoordinates.position(0);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, mCubeTextureCoordinates);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);

//Get Handle to Shape's Transformation Matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix");

//Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);

//Draw the triangle
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

//Disable Vertex Array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}

public static int loadTexture(final Context context, final int resourceId)
{
final int[] textureHandle = new int[1];

GLES20.glGenTextures(1, textureHandle, 0);

if (textureHandle[0] != 0)
{
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling

// Read in the resource
final Bitmap bitmap = BitmapFactory
.decodeResource(context.getResources(), resourceId, options);

// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);

// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_NEAREST);

// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
}

if (textureHandle[0] == 0)
{
throw new RuntimeException("Error loading texture.");
}

return textureHandle[0];
}
}

例如,http://changesuk.net/wp-content/uploads/2009/05/4-quadrants.jpg 处的图片已更改,因此数字的方向都正确,但在模式中

4 | 3
-----
2 | 1

如果我更改添加正方形坐标的顺序(例如从“左下角”开始),图像的象限会移动但也会围绕它们各自的中心旋转(在上图的情况下) ,数字将全部在他们的侧面或头部)。我查看了每一行代码,无法理解这里发生了什么。有没有人以前遇到过这种行为,或者有人可以解释可能导致这种行为的原因吗?

最佳答案

我已经查看 SO 一段时间了,但我从来没有机会回答问题。我知道这个问题已经有 5 个月了,但我还是会尽力回答。

基本上,您所做的是没有将纹理的角与顶点的角正确对齐。你明白了

4 | 3
-----
2 | 1

因为纹理的中心是正方形的右下角,并且纹理会重复,因此 4 和 2 在右边,而 3 在上面。

解决这个问题的方法是在你的顶点着色器中添加一个新的 vec4

    uniform vec4 pos;

并用x、y、宽度和高度填充它

    int pos = GLES20.glGetUniformLocation(mProgram, "pos");
GLES20.glUniform4f(pos, .5f, .5f, 1, 1); // x, y, width, height

现在改变这个

    v_TexCoordinate = a_TexCoordinate;

对此

    v_TexCoordinate = vec2((a_TexCoordinate.x - pos.x)/pos.z, (a_TexCoordinate.y - pos.y)/pos.w);

这应该可以解决问题。

关于Android OpenGL ES 2 纹理象限旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18285373/

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