opengles将位图放在球体之外

时间:2016-08-19 09:07:59

标签: android opengl-es

我想把纹理放在球体外面,我搜索一些链接

https://github.com/kibotu/net.gtamps/blob/refactoring3d/android/graphic/src/net/gtamps/android/renderer/graph/scene/primitives/Sphere.java

https://github.com/ejeinc/RajawaliCardboardExample

所有都将纹理放在球体内部。怎么做

我在球体内部做了纹理

public class SphereModel {
// Init variable value
private final int INVALID_STATE = -1;
int mProgram = INVALID_STATE;
int muMVPMatrixHandle = -1;
int muMMatrixHandle = -1;// 
int maCameraHandle = -1; // 
int maPositionHandle = -1; // 
int maNormalHandle = -1; //
int maTexCoorHandle = -1; // 
int maSunLightLocationHandle = -1;
int uDayTexHandle = -1;
String mVertexShader;
String mFragmentShader;
FloatBuffer mVertexBuffer;
FloatBuffer mTexCoorBuffer;
int vCount = 0;

float[] mvpM = new float[16];
float[] mM = new float[16];




public SphereModel(Resources r, float radius) {

    initVertexData(radius);

    initShader(r);

    Matrix.setIdentityM(mvpM, 0);
    Matrix.setIdentityM(mM, 0);

    Matrix.translateM(mM, 0, 0, 0, 0);
}


public void initVertexData(float r) {
    // ================begin============================
    final float UNIT_SIZE = 0.5f;
    ArrayList<Float> alVertix = new ArrayList<Float>();
    final float angleSpan = 10f;
    for (float vAngle = 90; vAngle > -90; vAngle = vAngle - angleSpan) {
        for (float hAngle = 360; hAngle > 0; hAngle = hAngle - angleSpan) {

            double xozLength = r * UNIT_SIZE
                    * Math.cos(Math.toRadians(vAngle));
            float x1 = (float) (xozLength * Math
                    .cos(Math.toRadians(hAngle)));
            float z1 = (float) (xozLength * Math
                    .sin(Math.toRadians(hAngle)));
            float y1 = (float) (r * UNIT_SIZE * Math.sin(Math
                    .toRadians(vAngle)));

            xozLength = r * UNIT_SIZE
                    * Math.cos(Math.toRadians(vAngle - angleSpan));
            float x2 = (float) (xozLength * Math
                    .cos(Math.toRadians(hAngle)));
            float z2 = (float) (xozLength * Math
                    .sin(Math.toRadians(hAngle)));
            float y2 = (float) (r * UNIT_SIZE * Math.sin(Math
                    .toRadians(vAngle - angleSpan)));

            xozLength = r * UNIT_SIZE
                    * Math.cos(Math.toRadians(vAngle - angleSpan));
            float x3 = (float) (xozLength * Math.cos(Math.toRadians(hAngle
                    - angleSpan)));
            float z3 = (float) (xozLength * Math.sin(Math.toRadians(hAngle
                    - angleSpan)));
            float y3 = (float) (r * UNIT_SIZE * Math.sin(Math
                    .toRadians(vAngle - angleSpan)));

            xozLength = r * UNIT_SIZE * Math.cos(Math.toRadians(vAngle));
            float x4 = (float) (xozLength * Math.cos(Math.toRadians(hAngle
                    - angleSpan)));
            float z4 = (float) (xozLength * Math.sin(Math.toRadians(hAngle
                    - angleSpan)));
            float y4 = (float) (r * UNIT_SIZE * Math.sin(Math
                    .toRadians(vAngle)));

            alVertix.add(x1);
            alVertix.add(y1);
            alVertix.add(z1);
            alVertix.add(x2);
            alVertix.add(y2);
            alVertix.add(z2);
            alVertix.add(x4);
            alVertix.add(y4);
            alVertix.add(z4);

            alVertix.add(x4);
            alVertix.add(y4);
            alVertix.add(z4);
            alVertix.add(x2);
            alVertix.add(y2);
            alVertix.add(z2);
            alVertix.add(x3);
            alVertix.add(y3);
            alVertix.add(z3);
        }
    }
    vCount = alVertix.size() / 3;

    float vertices[] = new float[vCount * 3];
    for (int i = 0; i < alVertix.size(); i++) {
        vertices[i] = alVertix.get(i);
    }

    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
    vbb.order(ByteOrder.nativeOrder());
    mVertexBuffer = vbb.asFloatBuffer();
    mVertexBuffer.put(vertices);
    mVertexBuffer.position(0);

    float[] texCoor = generateTexCoor(
            (int) (360 / angleSpan), 
            (int) (180 / angleSpan) 
    );
    ByteBuffer llbb = ByteBuffer.allocateDirect(texCoor.length * 4);
    llbb.order(ByteOrder.nativeOrder());
    mTexCoorBuffer = llbb.asFloatBuffer();
    mTexCoorBuffer.put(texCoor);
    mTexCoorBuffer.position(0);
}

public void initShader(Resources r) { 

    mVertexShader = ShaderUtil.loadFromAssetsFile("vertex_tex_f.sh", r);
    ShaderUtil.checkGlError("==ss==");

    mFragmentShader = ShaderUtil.loadFromAssetsFile("frag_tex_f.sh", r);

    ShaderUtil.checkGlError("==ss==");
    mProgram = ShaderUtil.createProgram(mVertexShader, mFragmentShader);

    maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");

    maTexCoorHandle = GLES20.glGetAttribLocation(mProgram, "aTexCoor");

    muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
}

public void drawSelf(Eye transform, int textureId) {

    GLES20.glUseProgram(mProgram);


    GLES20.glEnable(GLES20.GL_CULL_FACE);
    GLES20.glFrontFace(GLES20.GL_CW);




    if(ThunderConstant.MODE_CHOICE==1){

        if(ThunderConstant.TYPE_CHOICE==0){
            Matrix.setLookAtM(mM, 0, 0, 0, 0, 0f, 0f, -10f, 0f, 1f, 0f);
        }else if(ThunderConstant.TYPE_CHOICE==1){
            Matrix.setLookAtM(mM, 0, 0, 0, 0, 0f, 0f, -10f, 0f, 1f, 0f);
            Matrix.translateM(mM, 0, 0, -1.5f, 0);
        }else if(ThunderConstant.TYPE_CHOICE==2){

        }
    }else{

        if(ThunderConstant.TYPE_CHOICE==0){
            Matrix.setLookAtM(mM, 0, 0, 0, 0, 0f, 0f, -10f, 0f, 1f, 0f);
        }else if(ThunderConstant.TYPE_CHOICE==1){
            Matrix.setLookAtM(mM, 0, 0, 0, 0, 0f, 0f, -10f, 0f, 1f, 0f);
            Matrix.translateM(mM, 0, 0, -1.5f, 0);
        }else if(ThunderConstant.TYPE_CHOICE==2){

        }

    }



    Matrix.multiplyMM(mvpM, 0, transform.getEyeView(), 0, mM, 0);
    Matrix.multiplyMM(mvpM, 0, transform.getPerspective(0.1f, 200f), 0, mvpM, 0);

    if(PanoramaImageActivityNormalMode.isGestureControl){
        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false,
                MatrixState.getFinalMatrixOfFullImage(transform), 0);
    }else{
        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mvpM, 0);
    }


    GLES20.glVertexAttribPointer(

            maPositionHandle, 3, GLES20.GL_FLOAT, false, 3 * 4,
            mVertexBuffer);
    GLES20.glVertexAttribPointer(

            maTexCoorHandle, 2, GLES20.GL_FLOAT, false, 2 * 4,
            mTexCoorBuffer);

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);


    GLES20.glEnableVertexAttribArray(maPositionHandle);
    GLES20.glEnableVertexAttribArray(maTexCoorHandle);
    // GLES20.glEnableVertexAttribArray(maNormalHandle);

    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
}





public float[] generateTexCoor(int bw, int bh) {
    float[] result = new float[bw * bh * 6 * 2];
    // float sizew=1.0f/bw;
    // float sizeh=1.0f/bh;
    float sizew = 1.0f / bw;
    float sizeh = 1.0f / bh;
    int c = 0;
    for (int i = 0; i < bh; i++) {
        for (int j = 0; j < bw; j++) {

            float s = 1 - j * sizew;
            float t = i * sizeh;

            result[c++] = s;
            result[c++] = t;

            result[c++] = s;
            result[c++] = t + sizeh;

            result[c++] = s - sizew;
            result[c++] = t;

            //
            result[c++] = s - sizew;
            result[c++] = t;

            result[c++] = s;
            result[c++] = t + sizeh;

            result[c++] = s - sizew;
            result[c++] = t + sizeh;
        }
    }
    return result;

}

/**
 * recycle resource
 */
public void recyleRecource() {
    if (mProgram != INVALID_STATE) {
        GLES20.glDeleteProgram(mProgram);
        mProgram = INVALID_STATE;
    }
}

}

如何修改它使球体内部的纹理

1 个答案:

答案 0 :(得分:1)

一种简单的方法(但不推荐)是去除背面剔除。 See Here

真正的问题在于如何表示纹理坐标和曲面法线。想想球体的哪一侧是正面,哪一面是背面。如果你想要球体外部的纹理,那么缠绕顺序,表面法线和纹理坐标需要反映出来。

根据您提供的代码示例,您需要更改此代码中的绕组顺序和U,V

          for (c = 0; c <= stacks; c++) {
            float u = (float) c / (float) stacks; // [0,1]
            float theta2 = u * (float) (Math.PI * 2f); // [0,2PI]
            pos.set(n);
            pos.rotateY(theta2);

            posFull.set(pos);
            posFull.mulInPlace(dimension.x);

            mesh.vertices.addVertex(posFull.x, posFull.y, posFull.z, pos.x, pos.y, pos.z, emissive.r, emissive.g, emissive.b, emissive.a, u, v);
        }

想象一下在'mesh.vertices.addVertex'期间由此代码创建的三角形。对于每组三个顶点(每个三角形),您需要反转缠绕顺序,以便翻转三角形以呈现到外部。根据您使用的纹理,您可能还需要翻转传入的U,V坐标。

修改 我没有一个编辑器可以证明它,但你可能只需要反转for循环(向后迭代for循环)并以相反的顺序添加顶点以反转绕组。

这样的东西
for (c = stacks-1; c >= 0; --c) {
    ...
}