在 vuforia 示例中添加纹理
Add texture on vuforia example
我尝试在 Vuforia 上添加 2d 纹理 "Image Target part"。我尝试从我的另一个项目中添加一个 SquareTexture。
所以我有 class:
package com.vuforia.samples.VuforiaSamples.app.ImageTargets;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.util.Log;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
/**
* A two-dimensional square for use as a drawn object in OpenGL ES 2.0.
*/
public class SquareTexture {
private static int[] textureHandle;
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;\n" +
"attribute vec2 aPosition;\n" +
"attribute vec2 aTexPos;\n" +
"varying vec2 vTexPos;\n" +
"void main() {\n" +
" vTexPos = aTexPos;\n" +
" gl_Position = uMVPMatrix * vec4(aPosition.xy, 0.0, 1.0);\n" +
//" gl_Position = vec4(aPosition.xy, 0.0, 1.0);\n" +
"}";
private final String fragmentShaderCode =
"precision mediump float;\n"+
"uniform sampler2D uTexture;\n" +
"varying vec2 vTexPos;\n" +
"void main(void)\n" +
"{\n" +
//" gl_FragColor = texture2D(uTexture, vec2(vTexPos.y,vTexPos.x));\n" +
" gl_FragColor = vec4( 1,1,0,(vTexPos.x+vTexPos.y)/2.0);\n" +
"}";
private final FloatBuffer vertexBuffer;
private final FloatBuffer vertexTextureBuffer;
private final ShortBuffer drawListBuffer;
private final int mProgram;
private int mPositionHandle;
private int mTexturePosHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
// number of coordinates per vertex in this array
final int COORDS_PER_VERTEX = 2;
float squareCoords[] = {
-1.0f, 1.0f,
1.0f, 1.0f,
1.0f,-1.0f,
-1.0f,-1.0f,
};
float squareCoordstexture[] = {
0.0f, 0.0f, // vertex 3
0.0f, 1.0f, // vertex 1
1.0f, 1.0f, // vertex 0
1.0f, 0.0f, // vertex 2
}; // top right
private final short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
float color[] = { 0.2f, 0.709803922f, 0.898039216f, 1.0f };
/**
* Sets up the drawing object data for use in an OpenGL ES context.
*/
Context localContext;
public SquareTexture(Context context) {
localContext = context;
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
ByteBuffer bbt = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
squareCoordstexture.length * 4);
bbt.order(ByteOrder.nativeOrder());
vertexTextureBuffer = bbt.asFloatBuffer();
vertexTextureBuffer.put(squareCoordstexture);
vertexTextureBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(
// (# of coordinate values * 2 bytes per short)
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
checkGlError("glGetUniformLocation");
// prepare shaders and OpenGL program
int vertexShader = loadShader(
GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = 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
String LogInfo = GLES20.glGetProgramInfoLog(mProgram);
checkGlError("glGetUniformLocation");
}
int frame = 0;
public int loadTexture()
{
textureHandle = new int[80];
checkGlError("glGetUniformLocation");
for(int i=0;i<80;i++) {
GLES20.glGenTextures(1, textureHandle, i);
int id = localContext.getResources().getIdentifier("ppp" + i, "drawable", localContext.getPackageName());
// Log.d("loadtexture", id + " vs " + R.drawable.alpha0);
//final BitmapFactory.Options options = new BitmapFactory.Options();
//options.inScaled = false; // No pre-scaling
// Read in the resource
Bitmap bitmap = BitmapFactory.decodeResource(localContext.getResources(), id);
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[i]);
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);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap, 0);
bitmap.recycle();
}
/* GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 640, 480,
0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, IntBuffer.wrap(pixels));*/
// // since we're using a PNG file with transparency, enable alpha blending.
checkGlError("glGetUniformLocation");
//
//
// // Recycle the bitmap, since its data has been loaded into OpenGL.
return textureHandle[0];
}
/**
* Encapsulates the OpenGL ES instructions for drawing this shape.
*
* @param mvpMatrix - The Model View Project matrix in which to draw
* this shape.
*/
public void draw(float[] mvpMatrix) {
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
GLES20.glEnable(GLES20.GL_BLEND);
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//checkGlError("glGetUniformLocation");
mTexturePosHandle = GLES20.glGetAttribLocation(mProgram, "aTexPos");
//checkGlError("glGetUniformLocation");
// Enable a handle to the triangle vertices
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(
mPositionHandle, 2,
GLES20.GL_FLOAT, false,
8, vertexBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
//checkGlError("glGetUniformLocation");
GLES20.glVertexAttribPointer(
mTexturePosHandle, 2,
GLES20.GL_FLOAT, false,
8, vertexTextureBuffer);
GLES20.glEnableVertexAttribArray(mTexturePosHandle);
//checkGlError("glGetUniformLocation");
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
//checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
//checkGlError("glUniformMatrix4fv");
int uTexture = GLES20.glGetUniformLocation(mProgram, "uTexture");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[((frame++)/10)%80]);
//checkGlError("glGetUniformLocation");
GLES20.glUniform1i(uTexture, 0);
//checkGlError("glGetUniformLocation");
// GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Draw the square
GLES20.glDrawElements(
GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisable(GLES20.GL_BLEND);
frame++;
}
/**
* Utility method for compiling a OpenGL shader.
*
* <p><strong>Note:</strong> When developing shaders, use the checkGlError()
* method to debug shader coding errors.</p>
*
* @param type - Vertex or fragment shader type.
* @param shaderCode - String containing the shader code.
* @return - Returns an id for the shader.
*/
public static int loadShader(int type, String shaderCode){
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
/**
* Utility method for debugging OpenGL calls. Provide the name of the call
* just after making it:
*
* <pre>
* mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
* AGLRenderer.checkGlError("glGetUniformLocation");</pre>
*
* If the operation is not successful, the check throws an error.
*
* @param glOperation - Name of the OpenGL call to check.
*/
public static void checkGlError(String glOperation) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
Log.e("SquareTexture", glOperation + ": glError " + error);
throw new RuntimeException(glOperation + ": glError " + error);
}
}
}
我在 onSurfaceCreated 函数中添加了 SquareTexture,并在调用 ImageTargetRenderer class 的 renderFrame 时绘制它。
没有错误,只是纹理没有出现。在我的其他项目中,同样的 class 工作正常,但在这里我可以看到方形纹理。
编辑:谢谢,原来是比例问题,但现在我遇到了另一个麻烦。图片显示不正确,图片上有透明点
既然你说你没有 gl 错误,而且你没有提到它,我猜这个 class 来自一个没有 Vuforia 的项目,我的第一个怀疑是转换 - 它可能是绘制的,但超出屏幕或太少。检查你的绘制方式是否适合你的 Vuforia 项目的坐标系,从正方形的缩放开始 - 试着让它变得很大,看看它是否被绘制。
我尝试在 Vuforia 上添加 2d 纹理 "Image Target part"。我尝试从我的另一个项目中添加一个 SquareTexture。 所以我有 class:
package com.vuforia.samples.VuforiaSamples.app.ImageTargets;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.util.Log;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
/**
* A two-dimensional square for use as a drawn object in OpenGL ES 2.0.
*/
public class SquareTexture {
private static int[] textureHandle;
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;\n" +
"attribute vec2 aPosition;\n" +
"attribute vec2 aTexPos;\n" +
"varying vec2 vTexPos;\n" +
"void main() {\n" +
" vTexPos = aTexPos;\n" +
" gl_Position = uMVPMatrix * vec4(aPosition.xy, 0.0, 1.0);\n" +
//" gl_Position = vec4(aPosition.xy, 0.0, 1.0);\n" +
"}";
private final String fragmentShaderCode =
"precision mediump float;\n"+
"uniform sampler2D uTexture;\n" +
"varying vec2 vTexPos;\n" +
"void main(void)\n" +
"{\n" +
//" gl_FragColor = texture2D(uTexture, vec2(vTexPos.y,vTexPos.x));\n" +
" gl_FragColor = vec4( 1,1,0,(vTexPos.x+vTexPos.y)/2.0);\n" +
"}";
private final FloatBuffer vertexBuffer;
private final FloatBuffer vertexTextureBuffer;
private final ShortBuffer drawListBuffer;
private final int mProgram;
private int mPositionHandle;
private int mTexturePosHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
// number of coordinates per vertex in this array
final int COORDS_PER_VERTEX = 2;
float squareCoords[] = {
-1.0f, 1.0f,
1.0f, 1.0f,
1.0f,-1.0f,
-1.0f,-1.0f,
};
float squareCoordstexture[] = {
0.0f, 0.0f, // vertex 3
0.0f, 1.0f, // vertex 1
1.0f, 1.0f, // vertex 0
1.0f, 0.0f, // vertex 2
}; // top right
private final short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
float color[] = { 0.2f, 0.709803922f, 0.898039216f, 1.0f };
/**
* Sets up the drawing object data for use in an OpenGL ES context.
*/
Context localContext;
public SquareTexture(Context context) {
localContext = context;
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
ByteBuffer bbt = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
squareCoordstexture.length * 4);
bbt.order(ByteOrder.nativeOrder());
vertexTextureBuffer = bbt.asFloatBuffer();
vertexTextureBuffer.put(squareCoordstexture);
vertexTextureBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(
// (# of coordinate values * 2 bytes per short)
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
checkGlError("glGetUniformLocation");
// prepare shaders and OpenGL program
int vertexShader = loadShader(
GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = 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
String LogInfo = GLES20.glGetProgramInfoLog(mProgram);
checkGlError("glGetUniformLocation");
}
int frame = 0;
public int loadTexture()
{
textureHandle = new int[80];
checkGlError("glGetUniformLocation");
for(int i=0;i<80;i++) {
GLES20.glGenTextures(1, textureHandle, i);
int id = localContext.getResources().getIdentifier("ppp" + i, "drawable", localContext.getPackageName());
// Log.d("loadtexture", id + " vs " + R.drawable.alpha0);
//final BitmapFactory.Options options = new BitmapFactory.Options();
//options.inScaled = false; // No pre-scaling
// Read in the resource
Bitmap bitmap = BitmapFactory.decodeResource(localContext.getResources(), id);
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[i]);
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);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap, 0);
bitmap.recycle();
}
/* GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 640, 480,
0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, IntBuffer.wrap(pixels));*/
// // since we're using a PNG file with transparency, enable alpha blending.
checkGlError("glGetUniformLocation");
//
//
// // Recycle the bitmap, since its data has been loaded into OpenGL.
return textureHandle[0];
}
/**
* Encapsulates the OpenGL ES instructions for drawing this shape.
*
* @param mvpMatrix - The Model View Project matrix in which to draw
* this shape.
*/
public void draw(float[] mvpMatrix) {
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
GLES20.glEnable(GLES20.GL_BLEND);
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//checkGlError("glGetUniformLocation");
mTexturePosHandle = GLES20.glGetAttribLocation(mProgram, "aTexPos");
//checkGlError("glGetUniformLocation");
// Enable a handle to the triangle vertices
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(
mPositionHandle, 2,
GLES20.GL_FLOAT, false,
8, vertexBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
//checkGlError("glGetUniformLocation");
GLES20.glVertexAttribPointer(
mTexturePosHandle, 2,
GLES20.GL_FLOAT, false,
8, vertexTextureBuffer);
GLES20.glEnableVertexAttribArray(mTexturePosHandle);
//checkGlError("glGetUniformLocation");
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
//checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
//checkGlError("glUniformMatrix4fv");
int uTexture = GLES20.glGetUniformLocation(mProgram, "uTexture");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[((frame++)/10)%80]);
//checkGlError("glGetUniformLocation");
GLES20.glUniform1i(uTexture, 0);
//checkGlError("glGetUniformLocation");
// GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Draw the square
GLES20.glDrawElements(
GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisable(GLES20.GL_BLEND);
frame++;
}
/**
* Utility method for compiling a OpenGL shader.
*
* <p><strong>Note:</strong> When developing shaders, use the checkGlError()
* method to debug shader coding errors.</p>
*
* @param type - Vertex or fragment shader type.
* @param shaderCode - String containing the shader code.
* @return - Returns an id for the shader.
*/
public static int loadShader(int type, String shaderCode){
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
/**
* Utility method for debugging OpenGL calls. Provide the name of the call
* just after making it:
*
* <pre>
* mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
* AGLRenderer.checkGlError("glGetUniformLocation");</pre>
*
* If the operation is not successful, the check throws an error.
*
* @param glOperation - Name of the OpenGL call to check.
*/
public static void checkGlError(String glOperation) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
Log.e("SquareTexture", glOperation + ": glError " + error);
throw new RuntimeException(glOperation + ": glError " + error);
}
}
}
我在 onSurfaceCreated 函数中添加了 SquareTexture,并在调用 ImageTargetRenderer class 的 renderFrame 时绘制它。
没有错误,只是纹理没有出现。在我的其他项目中,同样的 class 工作正常,但在这里我可以看到方形纹理。
编辑:谢谢,原来是比例问题,但现在我遇到了另一个麻烦。图片显示不正确,图片上有透明点
既然你说你没有 gl 错误,而且你没有提到它,我猜这个 class 来自一个没有 Vuforia 的项目,我的第一个怀疑是转换 - 它可能是绘制的,但超出屏幕或太少。检查你的绘制方式是否适合你的 Vuforia 项目的坐标系,从正方形的缩放开始 - 试着让它变得很大,看看它是否被绘制。