OpenGL ES 2.0 测试版
OpenGL ES 2.0 Alpha
我正在尝试加载纹理 PNG(由 photoshop 导出)并在 Android 中的 OpenGL ES 2.0 中使用它,但纯色看起来像透明的(png 中的黑色圆圈完全是黑色)
我听说如果你将 png 缩放超过 50%,就会出现错误(我测试了更多和相同的缩放,所以我认为情况并非如此)
我还读到 BitmapFactory 不读取预乘 alpha PNG,我尝试了另一个应该可以工作但没有工作的功能(也许是错误的)
有什么方法可以达到正确的 alpha 值?
这是我的片段着色器:
precision mediump float; // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
uniform vec3 u_LightPos; // The position of the light in eye space.
uniform sampler2D u_Texture; // The input texture.
varying vec3 v_Position; // Interpolated position for this fragment.
varying vec3 v_Normal; // Interpolated normal for this fragment.
varying vec2 v_TexCoordinate; // Interpolated texture coordinate per fragment.
// The entry point for our fragment shader.
void main()
{
// Will be used for attenuation.
float distance = length(u_LightPos - v_Position);
// Get a lighting direction vector from the light to the vertex.
vec3 lightVector = normalize(u_LightPos - v_Position);
// Calculate the dot product of the light vector and vertex normal. If the normal and light vector are
// pointing in the same direction then it will get max illumination.
float diffuse = max(dot(v_Normal, lightVector), 0.0);
// Add attenuation.
diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance)));
// Add ambient lighting
diffuse = diffuse + 0.7;
// Multiply the color by the diffuse illumination level and texture value to get final output color.
gl_FragColor = (diffuse * texture2D(u_Texture, v_TexCoordinate));
}
这是我的绘制调用:
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glUseProgram(mMagiaProgramHandle);
mMagiaTextureCoordinateHandle = GLES20.glGetAttribLocation(mMagiaProgramHandle, "a_TexCoordinate");
mTexturePruebaUniformHandle = GLES20.glGetUniformLocation(mMagiaProgramHandle, "u_TextureVec");
coordinate.drawMagia(mPositionHandle, mNormalHandle, mMagiaTextureCoordinateHandle);
// This multiplies the view matrix by the model matrix, and stores the
// result in the MVP matrix
// (which currently contains model * view).
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
// Pass in the modelview matrix.
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0);
// This multiplies the modelview matrix by the projection matrix, and
// stores the result in the MVP matrix
// (which now contains model * view * projection).
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
// Pass in the combined matrix.
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Pass in the light position in eye space.
GLES20.glUniform3f(mLightPosHandle, mLightPosInEyeSpace[0], mLightPosInEyeSpace[1], mLightPosInEyeSpace[2]);
GLES20.glUniform2f(mTexturePruebaUniformHandle, Magia.posTextureX, Magia.posTextureY);
// Draw the square.
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
GLES20.glDisable(GLES20.GL_BLEND);
这是我的加载函数;
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];
}
不确定纹理本身是否也有问题,但您的着色器代码中肯定有某些东西可能会给您带来意想不到的结果:
gl_FragColor = (diffuse * texture2D(u_Texture, v_TexCoordinate));
由于您将所有颜色分量(包括 alpha)与 diffuse
相乘,只要 diffuse
的值小于 1.0,生成的颜色就会部分透明。生成的 alpha 将 diffuse
乘以您从纹理中获得的 alpha。
如果您想使用从纹理采样的 alpha 作为片段的 alpha,则不应将其与 diffuse
相乘。仅将 RGB 分量与 diffuse
相乘的代码可能如下所示:
vec4 texVal = texture2D(u_Texture, v_TexCoordinate);
gl_FragColor = vec4(diffuse * texVal.rgb, texVal.a);
我正在尝试加载纹理 PNG(由 photoshop 导出)并在 Android 中的 OpenGL ES 2.0 中使用它,但纯色看起来像透明的(png 中的黑色圆圈完全是黑色)
我听说如果你将 png 缩放超过 50%,就会出现错误(我测试了更多和相同的缩放,所以我认为情况并非如此)
我还读到 BitmapFactory 不读取预乘 alpha PNG,我尝试了另一个应该可以工作但没有工作的功能(也许是错误的)
有什么方法可以达到正确的 alpha 值?
这是我的片段着色器:
precision mediump float; // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
uniform vec3 u_LightPos; // The position of the light in eye space.
uniform sampler2D u_Texture; // The input texture.
varying vec3 v_Position; // Interpolated position for this fragment.
varying vec3 v_Normal; // Interpolated normal for this fragment.
varying vec2 v_TexCoordinate; // Interpolated texture coordinate per fragment.
// The entry point for our fragment shader.
void main()
{
// Will be used for attenuation.
float distance = length(u_LightPos - v_Position);
// Get a lighting direction vector from the light to the vertex.
vec3 lightVector = normalize(u_LightPos - v_Position);
// Calculate the dot product of the light vector and vertex normal. If the normal and light vector are
// pointing in the same direction then it will get max illumination.
float diffuse = max(dot(v_Normal, lightVector), 0.0);
// Add attenuation.
diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance)));
// Add ambient lighting
diffuse = diffuse + 0.7;
// Multiply the color by the diffuse illumination level and texture value to get final output color.
gl_FragColor = (diffuse * texture2D(u_Texture, v_TexCoordinate));
}
这是我的绘制调用:
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glUseProgram(mMagiaProgramHandle);
mMagiaTextureCoordinateHandle = GLES20.glGetAttribLocation(mMagiaProgramHandle, "a_TexCoordinate");
mTexturePruebaUniformHandle = GLES20.glGetUniformLocation(mMagiaProgramHandle, "u_TextureVec");
coordinate.drawMagia(mPositionHandle, mNormalHandle, mMagiaTextureCoordinateHandle);
// This multiplies the view matrix by the model matrix, and stores the
// result in the MVP matrix
// (which currently contains model * view).
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
// Pass in the modelview matrix.
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0);
// This multiplies the modelview matrix by the projection matrix, and
// stores the result in the MVP matrix
// (which now contains model * view * projection).
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
// Pass in the combined matrix.
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Pass in the light position in eye space.
GLES20.glUniform3f(mLightPosHandle, mLightPosInEyeSpace[0], mLightPosInEyeSpace[1], mLightPosInEyeSpace[2]);
GLES20.glUniform2f(mTexturePruebaUniformHandle, Magia.posTextureX, Magia.posTextureY);
// Draw the square.
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
GLES20.glDisable(GLES20.GL_BLEND);
这是我的加载函数;
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];
}
不确定纹理本身是否也有问题,但您的着色器代码中肯定有某些东西可能会给您带来意想不到的结果:
gl_FragColor = (diffuse * texture2D(u_Texture, v_TexCoordinate));
由于您将所有颜色分量(包括 alpha)与 diffuse
相乘,只要 diffuse
的值小于 1.0,生成的颜色就会部分透明。生成的 alpha 将 diffuse
乘以您从纹理中获得的 alpha。
如果您想使用从纹理采样的 alpha 作为片段的 alpha,则不应将其与 diffuse
相乘。仅将 RGB 分量与 diffuse
相乘的代码可能如下所示:
vec4 texVal = texture2D(u_Texture, v_TexCoordinate);
gl_FragColor = vec4(diffuse * texVal.rgb, texVal.a);