【问题标题】:applying texture to Cube, different texture on each face of cube将纹理应用于立方体,立方体的每个面上都有不同的纹理
【发布时间】:2017-01-30 21:59:17
【问题描述】:

我正在尝试使用 samplerCube 和 textureCube 在带有着色器的立方体上应用不同的纹理。

但我无法在立方体的面上绘制纹理,只有单一颜色出现。

Screenshots of output

下面是我的着色器代码:

顶点着色器

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, -2,2,2, -2,-2,2, 2,-2,2, //0-1-2-3 front
        2,2,2, 2,-2,2,  2,-2,-2, 2,2,-2,//0-3-4-5 right
        2,-2,-2, -2,-2,-2, -2,2,-2, 2,2,-2,//4-7-6-5 back
        -2,2,2, -2,2,-2, -2,-2,-2, -2,-2,2,//1-6-7-2 left
        2,2,2, 2,2,-2, -2,2,-2, -2,2,2, //top
        2,-2,2, -2,-2,2, -2,-2,-2, 2,-2,-2,//bottom
    };

short[] indeces = {0,1,2, 0,2,3,
            4,5,6, 4,6,7,
            8,9,10, 8,10,11,
            12,13,14, 12,14,15,
            16,17,18, 16,18,19,
            20,21,22, 20,22,23,
            };




float[] normals = {
                  0, 0, 1,   0, 0, 1,   0, 0, 1,   0, 0, 1,     //front
                   1, 0, 0,   1, 0, 0,   1, 0, 0,   1, 0, 0,     // right
                   0, 0,-1,   0, 0,-1,   0, 0,-1,   0, 0,-1,     //back
                   -1, 0, 0,  -1, 0, 0,  -1, 0, 0,  -1, 0, 0,     // left
                   0, 1, 0,   0, 1, 0,   0, 1, 0,   0, 1, 0,     //  top                  
                   0,-1, 0,   0,-1, 0,   0,-1, 0,   0,-1, 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, 3, GLES20.GL_FLOAT, false, 0, cubeBuffer);
        GLES20.glEnableVertexAttribArray(iPosition);

        GLES20.glVertexAttribPointer(iNormal, 3, GLES20.GL_FLOAT, false, 0, 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, 0, -xAngle, 0, 1, 0);
        Matrix.rotateM(m_fIdentity, 0, -yAngle, 1, 0, 0);
        Matrix.multiplyMM(m_fVPMatrix, 0, m_fViewMatrix, 0, m_fIdentity, 0);
        Matrix.multiplyMM(m_fVPMatrix, 0, m_fProjMatrix, 0, m_fVPMatrix, 0);
        GLES20.glUniformMatrix4fv(iVPMatrix, 1, false, m_fVPMatrix, 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_NEAREST);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_CUBE_MAP, 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, 0, GLES20.GL_RGBA, img.getWidth(),img.getHeight() , 0,GLES20.GL_RGBA ,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, 0, GLES20.GL_RGBA, img.getWidth(),img.getHeight(), 0,GLES20.GL_RGBA ,GLES20.GL_UNSIGNED_BYTE, fcbuffer);
            fcbuffer = null;
            img.recycle();

            img = BitmapFactory.decodeResource(curView.getResources(), 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, 0, GLES20.GL_RGBA, img.getWidth(),img.getHeight(), 0,GLES20.GL_RGBA ,GLES20.GL_UNSIGNED_BYTE, 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, 0, GLES20.GL_RGBA, img.getWidth(),img.getHeight(), 0,GLES20.GL_RGBA ,GLES20.GL_UNSIGNED_BYTE, fcbuffer);
            fcbuffer = null;
            img.recycle();

            img = BitmapFactory.decodeResource(curView.getResources(), 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, 0, GLES20.GL_RGBA,img.getWidth(),img.getHeight(), 0,GLES20.GL_RGBA ,GLES20.GL_UNSIGNED_BYTE, fcbuffer);
            fcbuffer = null;
            img.recycle();

            img = BitmapFactory.decodeResource(curView.getResources(), 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, 0, GLES20.GL_RGBA, img.getWidth(),img.getHeight(), 0,GLES20.GL_RGBA ,GLES20.GL_UNSIGNED_BYTE, fcbuffer);
            fcbuffer = null;
            img.recycle();

            GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_CUBE_MAP);

            return cubeTex[0];
    }

我无法理解我在哪里犯了错误。

如果您想查看完整代码。

解决方案:

纹理坐标使用相同的立方体绘制坐标

谢谢大家

CODE Link

【问题讨论】:

  • 请把你的答案变成下面的真实答案。您可以在两天后将其标记为已接受。这将使问题从未回答的问题标签中消失。

标签: android opengl-es-2.0 shader


【解决方案1】:

虽然问题现在已经解决,但我想解释一下为什么使用不同的坐标实际上有帮助(因为上面没有提到)。

当我第一次实现立方体映射时,我遇到了同样的错误,因为对立方体映射的工作方式有误解。 Cube-map 内部是一组 6 个 2D 纹理,排列在立方体的六个面上。从数学的角度来看,它定义了一个查找函数,其中参数是 3D 方向,输出是 RGBA 颜色。

这很重要,因为在上面的示例中,查找的参数是正常的。法线是一个方向,这是正确的。但法线在立方体的整个面上也是恒定的(除非计算平滑着色样式法线,但情况并非如此)。如果法线(查找的输入)是恒定的,那当然意味着输出(颜色)也必须是恒定的。我对此的误解是我认为 OpenGL 会以某种方式同时考虑 位置和方向,但不幸的是事实并非如此。

在这种特殊情况下,有趣的是,可以使用 cubeMap(position) 或 cubeMap(position + direction),得到非常相似的结果。这是因为立方体贴图的另一个重要属性,即在从纹理中读取颜色之前,首先对输入方向进行归一化(将长度更改为 1,而不更改其方向)。这在旧显卡上用于计算快速矢量归一化,使用特殊的立方体贴图纹理(因为在着色器中计算平方根比纹理查找慢)。

关于立方体的最后一个想法 - 立方体贴图并不是为立方体的每个面分配不同纹理的正确方法。它适用于简单的情况,但很难使其实用,例如在游戏中,因为 I) 一个立方体上不同纹理组合的数量可能需要不必要的大量纹理,并且 II) 因为这样,纹理重复不能使用。

【讨论】:

    【解决方案2】:

    您需要在您的应用程序中添加 devDept.DataSet.dll 并将其应用于您的对象:

    string brickMatName = "Wall bricks";
    viewportLayout1.Materials.Add(brickMatName, new Material(devDept.DataSet.DataSet.GetBricks()));
    

    【讨论】:

      猜你喜欢
      • 2012-11-01
      • 2013-06-29
      • 1970-01-01
      • 1970-01-01
      • 2013-10-10
      • 2012-08-11
      • 1970-01-01
      • 2013-02-10
      • 1970-01-01
      相关资源
      最近更新 更多