如何在 openGL 中同时保留立方体的颜色和纹理
How keep both colors of a cube and a texture in openGL
我构建了一个在 android 上显示 3d 立方体的简单应用程序。当我尝试添加纹理时出现问题。
我的纹理是 png 图像。我意识到如果我想用它们的原始颜色显示图像,我会失去立方体背景颜色。
为了达到目的我做了不同的组合,但是都失败了
"void main() {" +
" gl_FragColor = texture2D(u_Texture, v_TexCoordinate) + aColor;" +
"}"
结果:
Combination of texture an color
void main() {" +
" gl_FragColor = texture2D(u_Texture, v_TexCoordinate);" +
"}"
only texture
我想要的是保留立方体的颜色并以其原始颜色显示图像。
任何帮助将不胜感激,谢谢
这是我的Cubo class:
public class Cubo {
private Context context;
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"attribute vec4 aColor;" +
"varying vec4 vColor;" +
"attribute vec2 a_TexCoordinate;" +
"varying vec2 v_TexCoordinate;" +
"void main() {" +
" vColor=aColor;" +
" gl_Position = uMVPMatrix * vPosition;" +
" v_TexCoordinate = a_TexCoordinate;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform sampler2D u_Texture;" +
"uniform vec4 aColor;" +
"varying vec2 v_TexCoordinate;" +
"void main() {" +
" gl_FragColor = aColor + texture2D(u_Texture, v_TexCoordinate);" +
"}";
private final FloatBuffer vertexBuffer;
private final ShortBuffer drawListBuffer;
private FloatBuffer mTextureBuffer;
private final int mProgram;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
private int mTextureUniformHandle;
private int mTextureCoordinateHandle;
private final int mTextureCoordinateDataSize = 2;
static final int COORDS_PER_VERTEX = 3;
static float cubeCoords[] = {
-0.5f, 0.5f, 0.5f, // top left
-0.5f, -0.5f, 0.5f, // bottom left
0.5f, -0.5f, 0.5f, // bottom right
0.5f, 0.5f, 0.5f, // top right
-0.5f, 0.5f, -0.5f, // top left back
-0.5f, -0.5f, -0.5f, // bottom left back
0.5f, -0.5f, -0.5f, // bottom right back
0.5f, 0.5f, -0.5f // top right back
};
private final short drawOrder[] = {0, 1, 2, 0, 2, 3,
3, 2, 6, 3, 6, 7,
0, 3, 7, 0, 7, 4,
1, 5, 6, 1, 6, 2,
4, 5, 1, 4, 1, 0,
7, 6, 5, 7, 5, 4};
private final int vertexStride = COORDS_PER_VERTEX * 4;
float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 0.0f};
private float texture[] = {
// Mapping coordinates for the vertices
// Front face
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f
};
private int[] textures = new int[1];
public Cubo(Context context) {
this.context = context;
ByteBuffer bb = ByteBuffer.allocateDirect(
cubeCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(cubeCoords);
vertexBuffer.position(0);
ByteBuffer dlb = ByteBuffer.allocateDirect(
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
ByteBuffer byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
mTextureBuffer = byteBuf.asFloatBuffer();
mTextureBuffer.put(texture);
mTextureBuffer.position(0);
int vertexShader = MyGLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = MyGLRenderer.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
}
public void draw(float[] mvpMatrix) {
GLES20.glUseProgram(mProgram);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
//---------------textura-------------------
mTextureUniformHandle = GLES20.glGetUniformLocation(mProgram, "u_Texture");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgram, "a_TexCoordinate");
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false,
0, mTextureBuffer);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glUniform1i(mTextureUniformHandle, 0);
//------------------------------------------
GLES20.glDrawElements(
GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
public void loadTexture() {
GLES20.glGenTextures(1, textures, 0);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.casilla27, options);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
这是我的渲染器:
public class MyGLRenderer implements GLSurfaceView.Renderer {
private Cubo cubo;
private Context context;
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix_x = new float[16];
private final float[] mRotationMatrix_y = new float[16];
private final float[] mRotationMatrix = new float[16];
private float mXAngle;
private float mYAngle;
public MyGLRenderer(Context context) {
this.context = context;
}
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
GLES20.glClearDepthf(1.0f);
GLES20.glEnable(GL10.GL_DEPTH_TEST);
cubo = new Cubo(context);
cubo.loadTexture();
}
@Override
public void onSurfaceChanged(GL10 gl10, int i, int i1) {
GLES20.glViewport(0, 0, i, i1);
float ratio = (float) i / i1;
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
@Override
public void onDrawFrame(GL10 gl10) {
float[] scratch = new float[16];
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -4, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
Matrix.setRotateM(mRotationMatrix_x, 0, mYAngle, 1.0f, 0, 0);
Matrix.setRotateM(mRotationMatrix_y, 0, mXAngle, 0, 1.0f, 0);
Matrix.multiplyMM(mRotationMatrix, 0, mRotationMatrix_y, 0, mRotationMatrix_x, 0);
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
cubo.draw(scratch);
}
public static int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public float getmXAngle() {
return mXAngle;
}
public void setmXAngle(float mXAngle) {
this.mXAngle = mXAngle;
}
public float getmYAngle() {
return mYAngle;
}
public void setmYAngle(float mYAngle) {
this.mYAngle = mYAngle;
}
您必须mix
属性颜色和纹理颜色取决于纹理的 Alpha 通道:
void main() {
vec4 textureColor = texture2D(u_Texture, v_TexCoordinate);
gl_FragColor = vec4(mix(aColor.rgb, textureColor.rgb, textureColor.a), 1.0);
}
我构建了一个在 android 上显示 3d 立方体的简单应用程序。当我尝试添加纹理时出现问题。
我的纹理是 png 图像。我意识到如果我想用它们的原始颜色显示图像,我会失去立方体背景颜色。
为了达到目的我做了不同的组合,但是都失败了
"void main() {" +
" gl_FragColor = texture2D(u_Texture, v_TexCoordinate) + aColor;" +
"}"
结果:
Combination of texture an color
void main() {" +
" gl_FragColor = texture2D(u_Texture, v_TexCoordinate);" +
"}"
only texture
我想要的是保留立方体的颜色并以其原始颜色显示图像。
任何帮助将不胜感激,谢谢
这是我的Cubo class:
public class Cubo {
private Context context;
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"attribute vec4 aColor;" +
"varying vec4 vColor;" +
"attribute vec2 a_TexCoordinate;" +
"varying vec2 v_TexCoordinate;" +
"void main() {" +
" vColor=aColor;" +
" gl_Position = uMVPMatrix * vPosition;" +
" v_TexCoordinate = a_TexCoordinate;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform sampler2D u_Texture;" +
"uniform vec4 aColor;" +
"varying vec2 v_TexCoordinate;" +
"void main() {" +
" gl_FragColor = aColor + texture2D(u_Texture, v_TexCoordinate);" +
"}";
private final FloatBuffer vertexBuffer;
private final ShortBuffer drawListBuffer;
private FloatBuffer mTextureBuffer;
private final int mProgram;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
private int mTextureUniformHandle;
private int mTextureCoordinateHandle;
private final int mTextureCoordinateDataSize = 2;
static final int COORDS_PER_VERTEX = 3;
static float cubeCoords[] = {
-0.5f, 0.5f, 0.5f, // top left
-0.5f, -0.5f, 0.5f, // bottom left
0.5f, -0.5f, 0.5f, // bottom right
0.5f, 0.5f, 0.5f, // top right
-0.5f, 0.5f, -0.5f, // top left back
-0.5f, -0.5f, -0.5f, // bottom left back
0.5f, -0.5f, -0.5f, // bottom right back
0.5f, 0.5f, -0.5f // top right back
};
private final short drawOrder[] = {0, 1, 2, 0, 2, 3,
3, 2, 6, 3, 6, 7,
0, 3, 7, 0, 7, 4,
1, 5, 6, 1, 6, 2,
4, 5, 1, 4, 1, 0,
7, 6, 5, 7, 5, 4};
private final int vertexStride = COORDS_PER_VERTEX * 4;
float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 0.0f};
private float texture[] = {
// Mapping coordinates for the vertices
// Front face
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f
};
private int[] textures = new int[1];
public Cubo(Context context) {
this.context = context;
ByteBuffer bb = ByteBuffer.allocateDirect(
cubeCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(cubeCoords);
vertexBuffer.position(0);
ByteBuffer dlb = ByteBuffer.allocateDirect(
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
ByteBuffer byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
mTextureBuffer = byteBuf.asFloatBuffer();
mTextureBuffer.put(texture);
mTextureBuffer.position(0);
int vertexShader = MyGLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = MyGLRenderer.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
}
public void draw(float[] mvpMatrix) {
GLES20.glUseProgram(mProgram);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
//---------------textura-------------------
mTextureUniformHandle = GLES20.glGetUniformLocation(mProgram, "u_Texture");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgram, "a_TexCoordinate");
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false,
0, mTextureBuffer);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glUniform1i(mTextureUniformHandle, 0);
//------------------------------------------
GLES20.glDrawElements(
GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
public void loadTexture() {
GLES20.glGenTextures(1, textures, 0);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.casilla27, options);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
这是我的渲染器:
public class MyGLRenderer implements GLSurfaceView.Renderer {
private Cubo cubo;
private Context context;
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix_x = new float[16];
private final float[] mRotationMatrix_y = new float[16];
private final float[] mRotationMatrix = new float[16];
private float mXAngle;
private float mYAngle;
public MyGLRenderer(Context context) {
this.context = context;
}
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
GLES20.glClearDepthf(1.0f);
GLES20.glEnable(GL10.GL_DEPTH_TEST);
cubo = new Cubo(context);
cubo.loadTexture();
}
@Override
public void onSurfaceChanged(GL10 gl10, int i, int i1) {
GLES20.glViewport(0, 0, i, i1);
float ratio = (float) i / i1;
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
@Override
public void onDrawFrame(GL10 gl10) {
float[] scratch = new float[16];
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -4, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
Matrix.setRotateM(mRotationMatrix_x, 0, mYAngle, 1.0f, 0, 0);
Matrix.setRotateM(mRotationMatrix_y, 0, mXAngle, 0, 1.0f, 0);
Matrix.multiplyMM(mRotationMatrix, 0, mRotationMatrix_y, 0, mRotationMatrix_x, 0);
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
cubo.draw(scratch);
}
public static int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public float getmXAngle() {
return mXAngle;
}
public void setmXAngle(float mXAngle) {
this.mXAngle = mXAngle;
}
public float getmYAngle() {
return mYAngle;
}
public void setmYAngle(float mYAngle) {
this.mYAngle = mYAngle;
}
您必须mix
属性颜色和纹理颜色取决于纹理的 Alpha 通道:
void main() {
vec4 textureColor = texture2D(u_Texture, v_TexCoordinate);
gl_FragColor = vec4(mix(aColor.rgb, textureColor.rgb, textureColor.a), 1.0);
}