问题描述
|
我正在尝试使用samplerCube和textureCube在具有着色器的多维数据集上应用不同的纹理。
但是我无法在单一颜色的立方体表面上绘制纹理。
输出屏幕截图
以下是我的着色器代码:
顶点着色器
String strVShader = \"attribute vec4 a_position;\" +
\"uniform mat4 u_VPMatrix;\" +
\"attribute vec3 a_normal;\" +
\"varying vec3 v_normal;\" +
\"void main()\" +
\"{\" +
\"gl_Position = u_VPMatrix * a_position;\" +
\"v_normal = a_normal;\" +
\"}\";
片段着色器
String strFShader = \"precision mediump float;\" +
\"uniform samplerCube u_texId;\" +
\"varying vec3 v_normal;\" +
\"void main()\" +
\"{\" +
\"gl_FragColor = textureCube(u_texId,v_normal);\" +
\"}\";
立方体定义
float[] cube = {
2,2,-2,//0-1-2-3 front
2,//0-3-4-5 right
2,//4-7-6-5 back
-2,//1-6-7-2 left
2,//top
2,//bottom
};
short[] indeces = {0,1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,};
float[] normals = {
0,//front
1,// right
0,-1,//back
-1,// left
0,// top
0,// bottom
};
OnDrawFrame
public void onDrawFrame(GL10 arg0) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.gluseProgram(iProgId);
cubeBuffer.position(0);
GLES20.glVertexAttribPointer(iPosition,GLES20.GL_FLOAT,false,cubeBuffer);
GLES20.glEnabLevertexAttribArray(iPosition);
GLES20.glVertexAttribPointer(inormal,normBuffer);
GLES20.glEnabLevertexAttribArray(inormal);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_CUBE_MAP,iTexId);
GLES20.gluniform1i(iTexLoc,0);
Matrix.setIdentityM(m_fIdentity,0);
Matrix.rotateM(m_fIdentity,-xAngle,-yAngle,0);
Matrix.multiplyMM(m_fVPMatrix,m_fViewMatrix,m_fIdentity,m_fProjMatrix,m_fVPMatrix,0);
GLES20.gluniformMatrix4fv(iVPMatrix,0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES,36,GLES20.GL_UNSIGNED_SHORT,indexBuffer);
}
创建立方体贴图代码
public int CreateCubeTexture()
{
ByteBuffer fcbuffer = null;
int[] cubeTex = new int[1];
GLES20.glGenTextures(1,cubeTex,0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_CUBE_MAP,cubeTex[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_CUBE_MAP,GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_CUBE_MAP,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_CUBE_MAP,GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE);
Bitmap img = null;
img = BitmapFactory.decodeResource(curView.getResources(),R.raw.brick1);
fcbuffer = ByteBuffer.allocateDirect(img.getHeight() * img.getWidth() * 4);
img.copyPixelsToBuffer(fcbuffer);
fcbuffer.position(0);
Log.d(\"alpha\",\"\"+img.hasAlpha());
GLES20.glTexImage2D(GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X,GLES20.GL_RGBA,img.getWidth(),img.getHeight(),GLES20.GL_UNSIGNED_BYTE,fcbuffer);
fcbuffer = null;
img.recycle();
img = BitmapFactory.decodeResource(curView.getResources(),R.raw.brick2);
fcbuffer = ByteBuffer.allocateDirect(img.getHeight() * img.getWidth() * 4);
img.copyPixelsToBuffer(fcbuffer);
fcbuffer.position(0);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_CUBE_MAP_NEGATIVE_X,R.raw.brick3);
fcbuffer = ByteBuffer.allocateDirect(img.getHeight() * img.getWidth() * 4);
img.copyPixelsToBuffer(fcbuffer);
fcbuffer.position(0);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_Y,fcbuffer);
fcbuffer = null;
img.recycle();
img = BitmapFactory.decodeResource(curView.getResources(),R.raw.brick4);
fcbuffer = ByteBuffer.allocateDirect(img.getHeight() * img.getWidth() * 4);
img.copyPixelsToBuffer(fcbuffer);
fcbuffer.position(0);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,R.raw.brick5);
fcbuffer = ByteBuffer.allocateDirect(img.getHeight() * img.getWidth() * 4);
img.copyPixelsToBuffer(fcbuffer);
fcbuffer.position(0);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_Z,R.raw.brick6);
fcbuffer = ByteBuffer.allocateDirect(img.getHeight() * img.getWidth() * 4);
img.copyPixelsToBuffer(fcbuffer);
fcbuffer.position(0);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,fcbuffer);
fcbuffer = null;
img.recycle();
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_CUBE_MAP);
return cubeTex[0];
}
我无法理解我在哪里犯错。
如果要查看完整的代码。
解:
使用相同的立方体绘制坐标作为纹理坐标
谢谢大家
代码链接
解决方法
尽管现在已经解决了问题,但我想提供一个解释,说明为什么实际上使用其他坐标会有所帮助(因为上面没有列出)。
当我第一次实现多维数据集映射时,由于对多维数据集映射的工作方式的误解,我也遇到了同样的错误。多维数据集贴图在内部是一组6个2D纹理,排列在一个多维数据集的六个面上。从数学的角度来看,它定义了一个查找函数,其中参数是3D方向,输出是RGBA颜色。
这很重要,因为在上面的示例中,查找的参数是正常的。法线是一个方向,这是正确的。但是法线在立方体的整个面上也是恒定的(计算平滑阴影样式法线时除外,情况并非如此)。如果法线(查找的输入)是恒定的,那意味着输出(颜色)当然也必须是恒定的。我对此的误解是我以为OpenGL将以某种方式同时考虑位置和方向,但是不幸的是事实并非如此。
有趣的是,在这种情况下,既可以使用cubeMap(position)也可以使用cubeMap(position + direction),将获得非常相似的结果。这是由于立方体贴图的另一个重要属性,即在从纹理中读取颜色之前,首先将输入方向进行规范化(将长度更改为1,而不更改其方向)。使用特殊的立方体贴图纹理,这可用于较旧的图形卡以计算快速矢量归一化(因为在着色器中计算平方根比纹理查找要慢)。
关于立方体的最后一个想法-立方体贴图不是为立方体的每个面分配不同纹理的正确方法。它适用于简单的情况,但很难使其实用,例如在游戏中,由于I)一个多维数据集上不同纹理的组合数量可能会不必要地需要大量纹理,并且II)因为这样,不能使用纹理重复。
, 您需要在应用程序中添加devDept.DataSet.dll并将其应用于对象:
string brickMatName = \"Wall bricks\";
viewportLayout1.Materials.Add(brickMatName,new Material(devDept.DataSet.DataSet.GetBricks()));