Android:纹理显示为纯色
Android: texture shows up as solid color
我正在尝试让纹理显示在由三角形扇形制成的正方形上,该纹理由 Canvas 制成。
主要颜色是黄色,里面画了一个小盒子,但最终的纹理是纯黄色。
没有纹理的黄色方块(图片)
片段着色器:
public static final String fragmentShaderCode_TEXTURED =
"precision mediump float;" +
"varying vec2 v_texCoord;" +
"uniform sampler2D s_texture;" +
"void main() {" +
//"gl_FragColor = vColor;"+
" gl_FragColor = texture2D( s_texture, v_texCoord );" +
"}";
纹理生成:
public static int loadGLTexture(String s){
Rect r = new Rect();
ThreadDat.get().paint.getTextBounds(s, 0, 1, r); //get string dimensions, yeilds 8x9 pxls
Bitmap bitmap = Bitmap.createBitmap(bestSize(r.width()),bestSize(r.height()), Bitmap.Config.ARGB_8888);
//example size is 16x16pxls
Log.i("TextureSize", r.width() + " " + r.height());
Canvas c = new Canvas(bitmap);
//some temporary test code setting the background yellow
//Paint colors are stored per thread, only one right now
ThreadDat.get().paint.setARGB(255, 255, 255, 0);
c.drawRect(0, 0, c.getWidth(), c.getHeight(), ThreadDat.get().paint);
//type the letter, in this case "A" in blue
ThreadDat.get().paint.setARGB(255, 0, 0, 255);
ThreadDat.get().paint.setTypeface(Typeface.create("Consolas", Typeface.NORMAL));
c.drawText(s.charAt(0) + "", 0, 0, ThreadDat.get().paint);
//draw another square that is half width and height, should be Blue
c.drawRect(0, 0, c.getWidth() / 2, c.getHeight() / 2, ThreadDat.get().paint);
return loadTexture(bitmap);
}
抽奖代码:
@Override
public void draw() {
//clearing any error to check if program has an error
GLES20.glGetError();
//get the compiled shader for textured shapes
int prgm = MyGLRenderer.getSTRD_TXTR_SHDR();
GLES20.glUseProgram(prgm);
//check for new errors and log to logcat (nothing)
MyGLRenderer.logError();
//setup projection view matrix
float[] scratch = new float[16];
Matrix.setIdentityM(scratch, 0);
Matrix.multiplyMM(scratch, 0, MyGLRenderer.getmMVPMatrix(), 0, scratch, 0);
//apply translations to matrix
Matrix.translateM(scratch, 0, xOffset, yOffset, zOffset);
Matrix.setRotateEulerM(scratch, 0, yaw, pitch, roll);
//get vPosition variable handle from chosen shader
mPosHandle = GLES20.glGetAttribLocation(prgm, "vPosition");
GLES20.glEnableVertexAttribArray(mPosHandle);
GLES20.glVertexAttribPointer(mPosHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT,
false, VERTEX_STRIDE, vertexBuffer);
////pass color data (set to white)
//mColorHandle = GLES20.glGetUniformLocation(prgm, "vColor");
//GLES20.glUniform4fv(mColorHandle, 1, color, 0);
//use texture0
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
//use texture from -> int textureID = MyGLRenderer.loadGLTexture("A");
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
//get handel for "uniform sampler2D s_texture;" to set value
int txtureHandle = GLES20.glGetUniformLocation(prgm, "s_texture");
GLES20.glUniform1i(txtureHandle, 0); //set s_texture to use binded texture 0
//pass in texture coords (u,v / s,t)
int textureCoordHndl = GLES20.glGetAttribLocation(prgm, "a_texCoord");
GLES20.glVertexAttribPointer(textureCoordHndl, 2/*size, 2 points per vector*/,
GLES20.GL_FLOAT, false, 0, textureBuffer);
//pass in the model view projection matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(prgm, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, scratch, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, vertex_count);
GLES20.glDisableVertexAttribArray(mPosHandle);
MyGLRenderer.logError();
}
我尝试使用与此 example:
中使用的相同的坐标集
正方形的顶点:
{ 0, 0, 0, //bottom left
0, height, 0, //topLeft
width, 0, 0, // bottom Right
width, height, 0)}; //topRight
纹理坐标:
0.0f, 1.0f, // top left (V2)
0.0f, 0.0f, // bottom left (V1)
1.0f, 1.0f, // top right (V4)
1.0f, 0.0f // bottom right (V3)
Similar Issue
听起来纹理坐标确实存在问题。因为整个东西都是黄色的,所以我怀疑 v_texCoord
在你的片段着色器中总是 (0,0)
所以第一个纹理像素被重复了。
纹理本身似乎没问题,因为正在绘制颜色。如果没有纹理,您很可能会看到一个黑色矩形。
无论如何,要处理此类问题,您需要在调试、测试方面有点创造性。要测试坐标,请使用 gl_FragColor = vec4( v_texCoord.x, v_texCoord.y, .0, 1.0 );
。这应该输出一个渐变矩形,其中左上角是黑色,右上角是红色,左下角是绿色。如果您没有看到此结果,那么您的纹理坐标不正确。在这种情况下,首先检查 varying
是否从顶点着色器正确连接。您可以在顶点着色器中使用 v_texCoord = vec2(1.0, 0.0)
并且结果应该是一个红色矩形(假设您仍然在片段着色器中进行之前的测试)。如果矩形是红色的,那么问题很可能出在你的手柄上,而不是在着色器上(否则 varying 设置不正确。可能是命名不匹配)。检查句柄 textureCoordHndl
的值是多少。如果这是负值,则手柄未连接。这很可能是由于命名不匹配。
进一步检查:
您缺少纹理坐标属性的启用 GLES20.glEnableVertexAttribArray(textureCoordHndl);
。请记住,在使用之前必须启用每个属性。
我正在尝试让纹理显示在由三角形扇形制成的正方形上,该纹理由 Canvas 制成。 主要颜色是黄色,里面画了一个小盒子,但最终的纹理是纯黄色。
没有纹理的黄色方块(图片)
片段着色器:
public static final String fragmentShaderCode_TEXTURED =
"precision mediump float;" +
"varying vec2 v_texCoord;" +
"uniform sampler2D s_texture;" +
"void main() {" +
//"gl_FragColor = vColor;"+
" gl_FragColor = texture2D( s_texture, v_texCoord );" +
"}";
纹理生成:
public static int loadGLTexture(String s){
Rect r = new Rect();
ThreadDat.get().paint.getTextBounds(s, 0, 1, r); //get string dimensions, yeilds 8x9 pxls
Bitmap bitmap = Bitmap.createBitmap(bestSize(r.width()),bestSize(r.height()), Bitmap.Config.ARGB_8888);
//example size is 16x16pxls
Log.i("TextureSize", r.width() + " " + r.height());
Canvas c = new Canvas(bitmap);
//some temporary test code setting the background yellow
//Paint colors are stored per thread, only one right now
ThreadDat.get().paint.setARGB(255, 255, 255, 0);
c.drawRect(0, 0, c.getWidth(), c.getHeight(), ThreadDat.get().paint);
//type the letter, in this case "A" in blue
ThreadDat.get().paint.setARGB(255, 0, 0, 255);
ThreadDat.get().paint.setTypeface(Typeface.create("Consolas", Typeface.NORMAL));
c.drawText(s.charAt(0) + "", 0, 0, ThreadDat.get().paint);
//draw another square that is half width and height, should be Blue
c.drawRect(0, 0, c.getWidth() / 2, c.getHeight() / 2, ThreadDat.get().paint);
return loadTexture(bitmap);
}
抽奖代码:
@Override
public void draw() {
//clearing any error to check if program has an error
GLES20.glGetError();
//get the compiled shader for textured shapes
int prgm = MyGLRenderer.getSTRD_TXTR_SHDR();
GLES20.glUseProgram(prgm);
//check for new errors and log to logcat (nothing)
MyGLRenderer.logError();
//setup projection view matrix
float[] scratch = new float[16];
Matrix.setIdentityM(scratch, 0);
Matrix.multiplyMM(scratch, 0, MyGLRenderer.getmMVPMatrix(), 0, scratch, 0);
//apply translations to matrix
Matrix.translateM(scratch, 0, xOffset, yOffset, zOffset);
Matrix.setRotateEulerM(scratch, 0, yaw, pitch, roll);
//get vPosition variable handle from chosen shader
mPosHandle = GLES20.glGetAttribLocation(prgm, "vPosition");
GLES20.glEnableVertexAttribArray(mPosHandle);
GLES20.glVertexAttribPointer(mPosHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT,
false, VERTEX_STRIDE, vertexBuffer);
////pass color data (set to white)
//mColorHandle = GLES20.glGetUniformLocation(prgm, "vColor");
//GLES20.glUniform4fv(mColorHandle, 1, color, 0);
//use texture0
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
//use texture from -> int textureID = MyGLRenderer.loadGLTexture("A");
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
//get handel for "uniform sampler2D s_texture;" to set value
int txtureHandle = GLES20.glGetUniformLocation(prgm, "s_texture");
GLES20.glUniform1i(txtureHandle, 0); //set s_texture to use binded texture 0
//pass in texture coords (u,v / s,t)
int textureCoordHndl = GLES20.glGetAttribLocation(prgm, "a_texCoord");
GLES20.glVertexAttribPointer(textureCoordHndl, 2/*size, 2 points per vector*/,
GLES20.GL_FLOAT, false, 0, textureBuffer);
//pass in the model view projection matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(prgm, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, scratch, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, vertex_count);
GLES20.glDisableVertexAttribArray(mPosHandle);
MyGLRenderer.logError();
}
我尝试使用与此 example:
中使用的相同的坐标集正方形的顶点:
{ 0, 0, 0, //bottom left
0, height, 0, //topLeft
width, 0, 0, // bottom Right
width, height, 0)}; //topRight
纹理坐标:
0.0f, 1.0f, // top left (V2)
0.0f, 0.0f, // bottom left (V1)
1.0f, 1.0f, // top right (V4)
1.0f, 0.0f // bottom right (V3)
Similar Issue
听起来纹理坐标确实存在问题。因为整个东西都是黄色的,所以我怀疑 v_texCoord
在你的片段着色器中总是 (0,0)
所以第一个纹理像素被重复了。
纹理本身似乎没问题,因为正在绘制颜色。如果没有纹理,您很可能会看到一个黑色矩形。
无论如何,要处理此类问题,您需要在调试、测试方面有点创造性。要测试坐标,请使用 gl_FragColor = vec4( v_texCoord.x, v_texCoord.y, .0, 1.0 );
。这应该输出一个渐变矩形,其中左上角是黑色,右上角是红色,左下角是绿色。如果您没有看到此结果,那么您的纹理坐标不正确。在这种情况下,首先检查 varying
是否从顶点着色器正确连接。您可以在顶点着色器中使用 v_texCoord = vec2(1.0, 0.0)
并且结果应该是一个红色矩形(假设您仍然在片段着色器中进行之前的测试)。如果矩形是红色的,那么问题很可能出在你的手柄上,而不是在着色器上(否则 varying 设置不正确。可能是命名不匹配)。检查句柄 textureCoordHndl
的值是多少。如果这是负值,则手柄未连接。这很可能是由于命名不匹配。
进一步检查:
您缺少纹理坐标属性的启用 GLES20.glEnableVertexAttribArray(textureCoordHndl);
。请记住,在使用之前必须启用每个属性。