наложение текстуры на куб, разные текстуры на каждой грани куба - PullRequest
5 голосов
/ 04 июня 2011

Я пытаюсь наложить разные текстуры на куб с помощью шейдеров, используя samplerCube и textureCube.

Но я не могу нарисовать текстуру на гранях куба, появляется только один цвет.

Скриншоты вывода

Ниже приведен код моего шейдера:

Vertex Shader

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

Ответы [ 2 ]

4 голосов
/ 20 января 2012

, хотя вопрос теперь решен, я хотел бы предложить объяснение того, почему фактически помогло использование других координат (потому что это отсутствует выше).

Когда я впервые применил кубическое отображение, у меня возникла та же ошибка из-за неправильного представления о том, как работают кубические карты. Внутренняя карта куба представляет собой набор из 6 2D текстур, расположенных на шести гранях куба. С математической точки зрения он определяет функцию поиска, где аргументом является 3D direction , а выводом является цвет RGBA.

Это важно, потому что в приведенном выше примере аргумент для поиска был нормальным. Нормальное - это правильное направление. Но нормаль также постоянна по всей грани куба (за исключением случаев, когда вычисляются гладкие нормали стиля затенения, что было не так). Если нормаль (входная информация для поиска) постоянна, это означает, что, конечно, выходной сигнал (цвет) также должен быть постоянным. Мое заблуждение в этом заключалось в том, что я предполагал, что OpenGL каким-то образом будет учитывать как положение, так и направление , но, к сожалению, это не так.

Интересно, что в данном конкретном случае можно использовать cubeMap (позиция) или cubeMap (позиция + направление), и вы получите довольно похожий результат. Это из-за другого важного свойства кубических карт, и это направление ввода сначала нормализуется (изменена длина до 1, без изменения его направления) перед считыванием цвета из текстуры. Это использовалось на старых графических картах для вычисления быстрой нормализации вектора с использованием специальной текстуры карты куба (поскольку вычисление квадратного корня в шейдере было медленнее, чем поиск текстуры).

Последняя мысль о кубах - кубическая карта не является правильным способом присвоения различной текстуры каждой грани куба. Это работает для простых случаев, но было бы трудно сделать это практичным, например. в игре, потому что I) количество комбинаций различных текстур в одном кубе, вероятно, потребовало бы слишком много текстур, и II), потому что таким образом повторение текстуры не может быть использовано.

0 голосов
/ 30 января 2017

Вам необходимо добавить devDept.DataSet.dll в ваше приложение и применить его к вашему объекту:

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