gpt4 book ai didi

android - 如何在 Android OpenGL ES3.0 中将位图/图像纹理添加到表面?

转载 作者:行者123 更新时间:2023-11-29 22:58:48 27 4
gpt4 key购买 nike

对于 Android,我已经看到几个在 OpenGL ES1.x 和 2.x 中向表面添加位图纹理的示例,但似乎 API 对于 ES 3.x 有所改变(例如 glEnableClientState() 被删除)并且我我想知道需要向以下代码添加/更改什么才能将位图图像推送到我的立方体表面。我对在网上找到的这段代码进行了一些修改,它已经成功地在每个表面上绘制和旋转了一个具有不同颜色的立方体,但是,现在我想在每个表面上绘制特定的资源图像,而不仅仅是纯色。

这是 Cube.java 类:

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES30;
import android.opengl.GLUtils;
import android.util.Log;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

public class Cube {
private int mProgramObject;
private int mMVPMatrixHandle;
private int mColorHandle;
private FloatBuffer mVertices;

//initial size of the cube. set here, so it is easier to change later.
float size = 0.7f;

//this is the initial data, which will need to translated into the mVertices variable in the constructor.
float[] mVerticesData = new float[]{
////////////////////////////////////////////////////////////////////
// FRONT
////////////////////////////////////////////////////////////////////
// Triangle 1
-size, size, size, // top-left
-size, -size, size, // bottom-left
size, -size, size, // bottom-right
// Triangle 2
size, -size, size, // bottom-right
size, size, size, // top-right
-size, size, size, // top-left
////////////////////////////////////////////////////////////////////
// BACK
////////////////////////////////////////////////////////////////////
// Triangle 1
-size, size, -size, // top-left
-size, -size, -size, // bottom-left
size, -size, -size, // bottom-right
// Triangle 2
size, -size, -size, // bottom-right
size, size, -size, // top-right
-size, size, -size, // top-left

////////////////////////////////////////////////////////////////////
// LEFT
////////////////////////////////////////////////////////////////////
// Triangle 1
-size, size, -size, // top-left
-size, -size, -size, // bottom-left
-size, -size, size, // bottom-right
// Triangle 2
-size, -size, size, // bottom-right
-size, size, size, // top-right
-size, size, -size, // top-left
////////////////////////////////////////////////////////////////////
// RIGHT
////////////////////////////////////////////////////////////////////
// Triangle 1
size, size, -size, // top-left
size, -size, -size, // bottom-left
size, -size, size, // bottom-right
// Triangle 2
size, -size, size, // bottom-right
size, size, size, // top-right
size, size, -size, // top-left

////////////////////////////////////////////////////////////////////
// TOP
////////////////////////////////////////////////////////////////////
// Triangle 1
-size, size, -size, // top-left
-size, size, size, // bottom-left
size, size, size, // bottom-right
// Triangle 2
size, size, size, // bottom-right
size, size, -size, // top-right
-size, size, -size, // top-left
////////////////////////////////////////////////////////////////////
// BOTTOM
////////////////////////////////////////////////////////////////////
// Triangle 1
-size, -size, -size, // top-left
-size, -size, size, // bottom-left
size, -size, size, // bottom-right
// Triangle 2
size, -size, size, // bottom-right
size, -size, -size, // top-right
-size, -size, -size // top-left
};

float colorcyan[] = myColor.cyan();
float colorblue[] = myColor.blue();
float colorred[] = myColor.red();
float colorgray[] = myColor.gray();
float colorgreen[] = myColor.green();
float coloryellow[] = myColor.yellow();

private int numFaces = 6;
private int[] imageFileIDs = { // Image file IDs
R.drawable.geo1,
R.drawable.geo2,
R.drawable.geo3,
R.drawable.geo4,
R.drawable.geo5,
R.drawable.geo6
};
private int[] textureIDs = new int[numFaces];
private Bitmap[] bitmap = new Bitmap[numFaces];

//vertex shader code
String vShaderStr =
"#version 300 es \n"
+ "uniform mat4 uMVPMatrix; \n"
+ "in vec4 vPosition; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = uMVPMatrix * vPosition; \n"
+ "} \n";
//fragment shader code.
String fShaderStr =
"#version 300 es \n"
+ "precision mediump float; \n"
+ "uniform vec4 vColor; \n"
+ "out vec4 fragColor; \n"
+ "void main() \n"
+ "{ \n"
+ " fragColor = vColor; \n"
+ "} \n";

String TAG = "Cube";


//finally some methods
//constructor
public Cube(Context ctx) {

if (ctx == null)
throw new NullPointerException("3D rendering needs valid context.");

//first setup the mVertices correctly.
mVertices = ByteBuffer
.allocateDirect(mVerticesData.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
.put(mVerticesData);
mVertices.position(0);

//setup the shaders
int vertexShader;
int fragmentShader;
int programObject;
int[] linked = new int[1];

// Load the vertex/fragment shaders
vertexShader = PrimaryRenderer.LoadShader(GLES30.GL_VERTEX_SHADER, vShaderStr);
fragmentShader = PrimaryRenderer.LoadShader(GLES30.GL_FRAGMENT_SHADER, fShaderStr);

// Create the program object
programObject = GLES30.glCreateProgram();

if (programObject == 0) {
Log.e(TAG, "So some kind of error, but what?");
return;
}

GLES30.glAttachShader(programObject, vertexShader);
GLES30.glAttachShader(programObject, fragmentShader);

// Bind vPosition to attribute 0
GLES30.glBindAttribLocation(programObject, 0, "vPosition");

// Link the program
GLES30.glLinkProgram(programObject);

// Check the link status
GLES30.glGetProgramiv(programObject, GLES30.GL_LINK_STATUS, linked, 0);

if (linked[0] == 0) {
Log.e(TAG, "Error linking program:");
Log.e(TAG, GLES30.glGetProgramInfoLog(programObject));
GLES30.glDeleteProgram(programObject);
return;
}

// Store the program object
mProgramObject = programObject;
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;

for (int face = 0; face < numFaces; face++) {
bitmap[face] = BitmapFactory.decodeStream(
ctx.getResources().openRawResource(imageFileIDs[face]), null, options);
}

//now everything is setup and ready to draw.

}

public void draw(float[] mvpMatrix) {

// Use the program object
GLES30.glUseProgram(mProgramObject);

// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES30.glGetUniformLocation(mProgramObject, "uMVPMatrix");
PrimaryRenderer.checkGlError("glGetUniformLocation");

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

// Apply the projection and view transformation
GLES30.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
PrimaryRenderer.checkGlError("glUniformMatrix4fv");

int VERTEX_POS_INDX = 0;
mVertices.position(VERTEX_POS_INDX); //just in case. We did it already though.

//add all the points to the space, so they can be correct by the transformations.
//would need to do this even if there were no transformations actually.
GLES30.glVertexAttribPointer(VERTEX_POS_INDX, 3, GLES30.GL_FLOAT,
false, 0, mVertices);
GLES30.glEnableVertexAttribArray(VERTEX_POS_INDX);

//Now we are ready to draw the cube finally.
int startPos = 0;
int verticesPerface = 6;

//draw front face
GLES30.glUniform4fv(mColorHandle, 1, colorblue, 0);
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureIDs[0]);
GLES30.glDrawArrays(GLES30.GL_TRIANGLES, startPos, verticesPerface);
startPos += verticesPerface;

//draw back face
GLES30.glUniform4fv(mColorHandle, 1, colorcyan, 0);
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureIDs[1]);
GLES30.glDrawArrays(GLES30.GL_TRIANGLES, startPos, verticesPerface);
startPos += verticesPerface;

//draw left face
GLES30.glUniform4fv(mColorHandle, 1, colorred, 0);
GLES30.glDrawArrays(GLES30.GL_TRIANGLES, startPos, verticesPerface);
startPos += verticesPerface;

//draw right face
GLES30.glUniform4fv(mColorHandle, 1, colorgray, 0);
GLES30.glDrawArrays(GLES30.GL_TRIANGLES, startPos, verticesPerface);
startPos += verticesPerface;

//draw top face
GLES30.glUniform4fv(mColorHandle, 1, colorgreen, 0);
GLES30.glDrawArrays(GLES30.GL_TRIANGLES, startPos, verticesPerface);
startPos += verticesPerface;

//draw bottom face
GLES30.glUniform4fv(mColorHandle, 1, coloryellow, 0);
GLES30.glDrawArrays(GLES30.GL_TRIANGLES, startPos, verticesPerface);
//last face, so no need to increment.

}

public void loadTexture(GL10 gl) {
gl.glGenTextures(6, textureIDs, 0); // Generate texture-ID array for 6 IDs
// Generate OpenGL texture images
for (int face = 0; face < numFaces; face++) {
gl.glBindTexture(GLES30.GL_TEXTURE_2D, textureIDs[face]);
gl.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
gl.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap[face], 0);

bitmap[face].recycle();
}
}

}

======================

公共(public)方法 loadTexture() 作为 Cube 实例初始化的一部分从我的渲染器类中调用。它将 6 个位图中的每一个与 2D 纹理相关联,但是我缺少成功将纹理提供给引擎的代码。到目前为止,我看到的所有示例都只涉及 ES 1.x 和 ES 2.x,似乎与上述代码不兼容。请提供任何帮助。

最佳答案

您必须向顶点着色器 (vUV) 添加纹理坐标属性。当然你必须设置纹理坐标属性(类似于顶点坐标)。请注意纹理坐标在 [0.0, 1.0] 范围内,您需要一个纹理坐标属性 (u, v) vor 每个顶点坐标 (x, y, z):

GLES30.glVertexAttribPointer(TEX_COORD_INDX, 2, GLES30.GL_FLOAT, false, 0, mTexCoords);
GLES30.glEnableVertexAttribArray(TEX_COORD_INDX);

将纹理坐标传递给 fragment 着色器(out vec2 uv;):

#version 300 es

uniform mat4 uMVPMatrix;

in vec4 vPosition;
in vec2 vUV;

out vec2 uv;

void main()
{
uv = vUV;
gl_Position = uMVPMatrix * vPosition;
}

在 fragment 着色器 (u_texture) 中添加统一的纹理采样器。制服必须由纹理单元设置(例如,GL_TEXTURE0 为 0)。由于您使用纹理单元 0 并且 0 是默认初始化,因此您可以跳过此步骤。通过 texture 查找纹理并将颜色分配给 fragment 着色器输出:

#version 300 es
precision mediump float;

in vec2 vUV;

out vec4 fragColor;

uniform sampler2D u_texture;

void main()
{
vec4 color = texture(u_texture, uv.xy);
fragColor = color;
}

关于android - 如何在 Android OpenGL ES3.0 中将位图/图像纹理添加到表面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57165441/

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